2

我试图实现一个名为 UserControlParityTypeSelect的包含两个 RadioButton - Odd& Even,并且 UserControl 将调用一个 DependencyProperty ParityType,它将在双向绑定中使用。这个想法很简单 - 如果Odd选择ParityType应该返回 1,如果Even选择ParityType应该返回 0。
这是代码 -

XAML(用户控件):

<StackPanel Orientation="Horizontal">
    <RadioButton Name="rdoOdd" Content="Odd" Margin="5" Checked="rdoOdd_CheckedChnaged" Unchecked="rdoOdd_CheckedChnaged" />
    <RadioButton Name="rdoEven" Content="Even" Margin="5"/>
</StackPanel>  

代码隐藏(用户控件):

public partial class ParityTypeSelect : UserControl
{
    //Some Code

    static ParityTypeSelect()
    {
        FrameworkPropertyMetadata parityTypeMetaData =
            new FrameworkPropertyMetadata(new PropertyChangedCallback(OnParityTypeChanged),
                                          new CoerceValueCallback(CoerceParityTypeValue));
        ParityTypeProperty = DependencyProperty.Register("ParityType", typeof(int?), typeof(ParityTypeSelect),
                                                         parityTypeMetaData,
                                                         new ValidateValueCallback(ValidateParityTypeValue));
    }

    public static readonly DependencyProperty ParityTypeProperty;
    public int? ParityType
    {
        get { return (int?)GetValue(ParityTypeProperty); }
        set { SetValue(ParityTypeProperty, value); }
    }

    private static void OnParityTypeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        ParityTypeSelect select = (ParityTypeSelect)d;
        int? newValue = (int?)e.NewValue;

        if (newValue != null && newValue <= 1)
        {
            if (newValue == 1)
                select.rdoOdd.IsChecked = true;
            else
                select.rdoEven.IsChecked = true;
        }
        else
            return;
    }

    private void rdoOdd_CheckedChnaged(object sender, RoutedEventArgs e)
    {
        RadioButton radioButton = (RadioButton)sender;
        if (radioButton.IsChecked != null)
        {
            if (radioButton.IsChecked.Value)
                SetValue(ParityTypeProperty, 1);
            else
                SetValue(ParityTypeProperty, 0);
        }
    }

    //Some more Code
}  

XAML(消费者):

<StackPanel>
     <aucl:ParityTypeSelect ParityType="{Binding Path=Format.FisrtBitType, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>                
</StackPanel>  

...而且它正在工作。但问题是,这是我第一次实现 DependencyProperty。所以我有点担心我是否做得对。我是否OnParityTypeChanged以正确的方式使用该方法?使用rdoOdd_CheckedChnaged事件处理程序设置属性值可以吗?有没有更好或更合适的方法来完成整个实现?我一直期待高质量的编码。因此,任何建议,改进建议,来自WPF人们的评论将不胜感激。

4

2 回答 2

1

我试图在评论中写这个,但我会单独回答。我会绑定属性,而不是在后面的代码中进行。您将需要一个转换器,因为 int? 将需要转换为布尔值。为了使转换器尽可能通用,我将使用EqualityConverter您可以像这样绑定的转换器:

<RadioButton Content="Odd" Margin="5" IsChecked="{Binding ParityTypeSelect,Mode=TwoWay,Converter={StaticResource equalityConverter}, ConverterParameter=1}" />

转换器的代码在这里:

public class EqualityConverter : IValueConverter
{
    public object TrueValue { get; set; }
    public object FalseValue { get; set; }

    public EqualityConverter()
    {
        //default the TrueValue and FalseValue to true and false.
        //this way we can easily use the same converter for simple comparison or as an IIF statement
        TrueValue = true;
        FalseValue = false;
    }
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value == null && parameter == null) return TrueValue;
        if (value == null && parameter != null) return FalseValue;

        //in some cases we might need to compare an enum value to an integer.
        //this will fail unless we specifically convert them
        if (value is int && parameter is Enum)
            parameter = System.Convert.ToInt32(parameter);
        else if (value is Enum && parameter is int)
            value = System.Convert.ToInt32(value);

        return value.Equals(parameter) ? TrueValue : FalseValue;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value == null && TrueValue == null) return true;
        if (value == null && FalseValue == null) return false;
        if (value.Equals(TrueValue)) return true;
        return false;
    }
}

我要说的其他几件事:-与其使用用户控件,不如从 Control 继承(就像标准类一样,没有 xaml)。然后将 xaml 放入名为 Generic.xaml 的文件中。涉及的内容很少,因此您需要搜索详细信息 - 您对 CoerceParityTypeValue 和 ValidateParityTypeValue 进行了不必要的调用,您可以忽略这些。- 定义依赖道具时,只需键入“propdp”(不带引号)并按下选项卡 - 通常控件上的控件以 PART_ 开头,例如 PART_OddButton

编辑:这是一篇似乎显示要点但并不完整的文章: http ://wpftutorial.net/HowToCreateACustomControl.html

于 2012-07-19T01:39:22.073 回答
0

但有一件事可能会更好,那就是不是在更改的事件代码中设置单选按钮的值,而是可以将它们绑定在 xaml 中,例如

<RadioButton Name="rdoOdd" Content="Odd" Margin="5" IsChecked="{Binding ParityTypeSelect,Mode=TwoWay,Converter=StaticResource booltoNullIntConverter }" />

booltoNullIntConverter 是一个转换器,可根据您的要求将 bool 更改为 null int。我希望这将有所帮助。

于 2012-07-19T00:55:27.540 回答