2012-07-19 30 views
2

我是想实现一个用户控件称为ParityTypeSelect包含两个单选按钮 - Odd & Even,并且用户控件是有一个DependencyProperty称为ParityType这是会在双向绑定使用。这个想法很简单 - 如果Odd选择ParityType应该返回1,如果Even选择ParityType应该返回0
下面的代码 -在UserControl中实现双向绑定的自定义DependencyProperty的适当方法是什么?

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事件处理程序来设置proerty值是否正常?有没有更好或更合适的方法来完成这整个实施?我一直期待着高质量的编码。所以任何建议,改进建议,WPF家伙的意见将非常感谢。

回答

1

我试图在注释中写的,但我会做它作为一个seprate答案。我会绑定属性而不是在后面的代码中执行它。你会需要一个转换器,因为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; 
    } 
} 

一些其他的东西,我会说: - 而不是使用usercontrol,你最好从Control继承(就像一个标准类,不需要xaml)。然后将xaml放入名为Generic.xaml的文件中。有一点涉及到的东西,所以你需要搜索的细节 - 你有不必要的调用CoerceParityTypeValue和ValidateParityTypeValue,你可以不要这些。 - 当定义依赖道具只需键入“propdp”(不带引号),并推动片 - 通常是在控制控件命名开始PART_,如PART_OddButton

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

+0

感谢那个“prpodp”魔术 - 虽然它提供了一个'UIPropertyMetadata',而不是'FrameworkPropertyMetadata',但它不知道类似这样的东西。我知道你建议使用'CustomControl'而不是'UserControl'。我不明白的是'IValueConverter'取代5/6行代码的优点。是不是这个'SomeProperty =“{Binding ... ...}''语法总是在场景后面生成一个事件处理程序? – atiyar 2012-07-19 02:07:14

+0

有很多类似的片段,比如“cw”,“ctor”等。如果你需要FrameworkPropertyMetadata,那么你可以改变它。好处是有人可以将界面替换为您的控件,并将其制作成任何他们喜欢的东西,例如红色/绿色按钮。因为xaml中的逻辑可以完成。我还发现,当事件在加载过程中出现时序问题时变得更加复杂时,使用这些事件会变得困难。关于幕后的事件处理程序,我会说这很可能。它需要以某种方式利用这些变化。 – MikeKulls 2012-07-19 06:05:13

0

但有一点可能会更好,这是不是设置,您可以将它们绑定在XAML像

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

booltoNullIntConverter在改变事件的代码单选按钮的值是改变布尔为空INT根据转换器满足您的要求。我希望这将有所帮助。

+0

ParityType的值是一个int?不是布尔 – 2012-07-19 01:05:12

+0

我认为这只是回到前面,它应该是一个nullint布尔转换器。虽然我会认为一个平等转换器会更好地处理一个带有该值的参数。 – MikeKulls 2012-07-19 01:08:14

+0

@Nero'newvalue'作为第一个参数传入转换器。您可以使用ConverterParameter传递附加参数。我只需写一个'EqualityConverted'并将值传递给ConverterParameter – MikeKulls 2012-07-19 01:24:14

相关问题