2012-07-19 33 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

相關問題