WPF 将值发送到可重用的用户控件

WPF sending value to reusable usercontrol

我认为这是 WFP 中级内容的初学者问题。 我有一个用户控件,它使用两个普通按钮充当单选按钮: (按钮改变颜色以显示当前选择)

<UserControl x:Class="UI.UserControls.RadioUC" Loaded="UserControl_Loaded">
<Stackpanel DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}}">

    <TextBlock Text="{Binding Path=Title}"/>

    <Button x:Name="BtnYes" Content="YES" Click="BtnYes_Click">
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="Click">
                <i:InvokeCommandAction Command="{Binding Command}"/>
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </Button>

        <Button x:Name="BtnNo" Content="NO" Click="BtnNo_Click">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="Click">
                    <i:InvokeCommandAction Command="{Binding Command}"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </Button>
</Stackpanel>
</UserControl>

代码隐藏由 2 个依赖属性 Title 和 IsYes 组成。 当使用点击事件点击按钮时,IsYes 属性 被修改。

public static readonly DependencyProperty TitleProperty = DependencyProperty.Register("Title", typeof(string), typeof(RadioUC),
        new FrameworkPropertyMetadata(default(string), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

public static readonly DependencyProperty IsYesProperty = DependencyProperty.Register("IsYes", typeof(bool), typeof(RadioUC),
        new FrameworkPropertyMetadata(default(bool), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

public bool IsYes {
        get { return (bool)GetValue(IsYesProperty); }
        set { SetValue(IsYesProperty, value); }
    }

public String Title {
        get { return (String)GetValue(TitleProperty); }
        set { SetValue(TitleProperty, value); }
    }

private void BtnYes_Click(object sender, RoutedEventArgs e)
    {
        IsYes = true;
        //BtnYes.Background = new SolidColorBrush(Colors.ForestGreen);
        //BtnNo.Background = new SolidColorBrush(Colors.Gray);
    }

private void BtnNo_Click(object sender, RoutedEventArgs e)
    {
        IsYes = false;
        //BtnNo.Background = new SolidColorBrush(Colors.ForestGreen);
        //BtnYes.Background = new SolidColorBrush(Colors.Gray);
    }

最后是我的使用方式:

<uc:RadioUC Title="Is it YES" IsYes="{Binding IsLocalYes, Mode=TwoWay}"/>

当按钮被单独点击时,用户控件的IsYes 属性修改成功。没有问题。问题是当我在用户控件的托管 window 中以编程方式修改 IsLocalYes 时,此更改不会传播到用户控件中。所以问题是,当 IsLocalYes 属性 发生变化时,如何修改用户控件的 IsYes 属性?

与其创建自己的 UserControl,不如使用 ToggleButton 并更改 ControlTemplate/Style

另请阅读此 article


解法:

切换按钮样式:

<Style x:Key="YesNoToggleButtonStyle" TargetType="ToggleButton" BasedOn="{StaticResource {x:Type ToggleButton}}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ToggleButton}">
                <Grid x:Name="templateRoot" Background="Transparent" SnapsToDevicePixels="True">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*"/>
                        <ColumnDefinition Width="Auto"/>
                    </Grid.ColumnDefinitions>
                    <ContentPresenter x:Name="contentPresenter" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                    <StackPanel Grid.Column="1" Orientation="Horizontal">
                        <Grid x:Name="PART_GRIDYES" Background="Gray" MinWidth="6" MinHeight="6">
                            <TextBlock VerticalAlignment="Center" HorizontalAlignment="Center">YES</TextBlock>
                        </Grid>
                        <Grid x:Name="PART_GRIDNO" Background="Gray" MinWidth="6" MinHeight="6">
                            <TextBlock VerticalAlignment="Center" HorizontalAlignment="Center">NO</TextBlock>
                        </Grid>
                    </StackPanel>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsChecked" Value="true">
                        <Setter TargetName="PART_GRIDYES" Property="Background" Value="ForestGreen"></Setter>
                    </Trigger>
                    <Trigger Property="IsChecked" Value="false">
                        <Setter TargetName="PART_GRIDNO" Property="Background" Value="ForestGreen"></Setter>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

这样使用:

<ToggleButton Style="{StaticResource YesNoToggleButtonStyle}" IsChecked="{Binding IsLocalYes, Mode=TwoWay}">Is it YES</ToggleButton>