2011-10-15 73 views
0

我目前正在構建一堆常用控件,它們基本上只是通過添加標籤和類似的東西來擴展默認的Silverlight控件......但是我很難得到一些綁定工作...下面是什麼目前不工作的一些例子:與自定義控件和綁定的問題

UPDATE:

這裏的一些背景來幫助理解這個問題:

public class ComboboxField : Field 
{ 

    public string SelectedValuePath 
    { 
     get { return (string)this.GetValue(SelectedValuePathProperty); } 
     set { this.SetValue(SelectedValuePathProperty, value); } 
    } 
    public static readonly DependencyProperty SelectedValuePathProperty = 
    DependencyProperty.Register("SelectedValuePath", typeof(string), typeof(ComboboxField), new PropertyMetadata(string.Empty)); 


    public string DisplayMemberPath 
    { 
     get { return (string)this.GetValue(DisplayMemberPathProperty); } 
     set { this.SetValue(DisplayMemberPathProperty, value); } 
    } 
    public static readonly DependencyProperty DisplayMemberPathProperty = 
     DependencyProperty.Register("DisplayMemberPath", typeof(string), typeof(ComboboxField), new PropertyMetadata(string.Empty, null)); 



    public IEnumerable ItemsSource 
    { 
     get { return (IEnumerable)this.GetValue(ItemsSourceProperty); } 
     set { this.SetValue(ItemsSourceProperty, value); } 
    } 

    public static readonly DependencyProperty ItemsSourceProperty = 
    DependencyProperty.Register("ItemsSource", typeof(Object), typeof(ComboboxField), new PropertyMetadata(new List<object>())); 



    public object SelectedValue 
    { 
     get { return (object)GetValue(SelectedValueProperty); } 
     set { SetValue(SelectedValueProperty, value); } 
    } 

    public static readonly DependencyProperty SelectedValueProperty = 
     DependencyProperty.Register("SelectedValue", typeof(object), typeof(ComboboxField), new PropertyMetadata(null, (s, e) => { s.SetValue(Field.ValueProperty, SelectedValueProperty);})); 

    #region Ctors 
    public ComboboxField(FieldDescription fieldDescription, Form parentForm) : base(fieldDescription, parentForm) 
    { 
     this.Template = Application.Current.Resources["ComboBoxDefaultTemplate"] as ControlTemplate; 
    } 

    public ComboboxField() : base(new FieldDescription(Guid.NewGuid(), "ComboboxField1", FieldType.Collection), null) 
    { 
     this.Template = Application.Current.Resources["ComboBoxDefaultTemplate"] as ControlTemplate; 
    } 
    #endregion 

} 

控件模板: (去掉了一些無關緊要的東西)

<ControlTemplate x:Name="ComboBoxDefaultTemplate" TargetType="my:ComboboxField"> 
      <Grid> 
       <Grid.RowDefinitions> 
        <RowDefinition Height="Auto" /> 
        <RowDefinition Height="Auto" /> 
       </Grid.RowDefinitions> 
       <Grid.ColumnDefinitions> 
        <ColumnDefinition Width="{TemplateBinding LabelColumnWidth}" /> 
        <ColumnDefinition Width="{TemplateBinding FieldColumnWidth}" /> 
       </Grid.ColumnDefinitions> 
       <TextBlock Grid.Row="0" Grid.Column="0" Style="{TemplateBinding TitleStyle}" Text="{TemplateBinding Title}"></TextBlock> 
       <TextBlock Text="*" Grid.Row="0" Grid.Column="0" Visibility="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Required, Converter={StaticResource boolToVisibility}}" Width="5" /> 
       <TextBlock Grid.Row="1" Grid.Column="0" Style="{TemplateBinding SummaryStyle}" Text="{TemplateBinding Summary}" Grid.ColumnSpan="2"></TextBlock> 
<ComboBox Style="{TemplateBinding FieldStyle}" Grid.Row="0" Grid.Column="1" 
          ItemsSource="{TemplateBinding ItemsSource}" 
          SelectedValue="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=SelectedValue, Mode=TwoWay}" 
          SelectedValuePath="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=SelectedValuePath, Mode=TwoWay}" 
          DisplayMemberPath="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=DisplayMemberPath, Mode=TwoWay}"></ComboBox> 
      </Grid> 
     </ControlTemplate> 

我試圖使用它的方式:

<cc:ComboboxField Grid.Row="10" TitleStyle="{StaticResource labelStyle}" 
            Title="Countries" ItemsSource="{Binding Countries}" 
            SelectedValuePath="CountryId" DisplayMemberPath="CountryId" 
            SelectedValue="{Binding Path=SelectedCountry, Mode=TwoWay}" /> 

我在做什麼錯在這裏?

+1

NotifyPropertyChanged調用是多餘的;默認樣式應放置在Themes/Generic.xaml文件中,不要使用任何鍵。您也可以在調試應用程序時查看輸出窗口,顯示所有綁定錯誤。如果綁定錯誤顯示在應用程序中,則可以將該信息添加到問題中。 – vorrtex

+0

@vorrtex:我一直想知道我怎樣才能弄清楚我的綁定是否有問題,這要感謝Output窗口提示。 :) – Kassem

回答

1

我可以立即看到你的依賴屬性的一些問題。

首先,我有一個與依賴屬性工作金科玉律,你的代碼侵犯了:

的CLR屬性的getter只能包含一個調用的GetValue和二傳手必須只包含給setValue的調用。

例如,SelectedValuePath屬性應該如下所示:如果想改變使用綁定,動畫或樣式的依賴屬性的值

public string SelectedValuePath 
{ 
    get { return (string)this.GetValue(SelectedValuePathProperty); } 
    set { this.SetValue(SelectedValuePathProperty, value); } 
} 

Silverlight不打電話給你的財產。如果你放棄了任何setter的斷點,你會發現他們不會像你所期望的那樣頻繁發生。

您可以將兩個依賴項屬性綁定在一起,而不需要執行任何一端的類INotifyPropertyChanged。我假設您的NotifyPropertyChanged方法正在觸發您應該能夠移除的PropertyChanged事件。

另外,如果你想Value屬性設置爲每次後者的變化,你需要一個PropertyChangedCallback添加到SelectedValue依賴屬性的SelectedValue屬性的值。

其次,SelectedValuePathProperty,DisplayMemberPathPropertyItemsSourceProperty的依賴屬性註冊是錯誤的。他們都將其所有者類別指定爲Field,而不是由ComboboxField類別擁有。

最後,你說你是

有一個很難得到一些綁定工作

你不告訴我們你的問題是什麼。你期待的代碼是什麼,它究竟在做什麼?鑑於我沒有你的Form,FieldFieldDescription類,也沒有你的FieldType枚舉,我不能運行你的代碼,所以我不能再真正幫助你。

+0

這絕對有幫助,我會解決這些問題,並在完成工作的情況下回復反饋。否則,我會試着更好地解釋這個問題,所以也許你可以幫忙解決這個問題。感謝您的輸入。 – Kassem

+0

現在一切都很好,謝謝。所以讓我弄清楚,我的自定義控件不應該實現INotifyPropertyChanged,對吧? – Kassem

+0

你是對的,自定義控件不應該實現INotifyPropertyChanged。 –