2009-04-02 4 views
3

При использовании привязки данных в WPF объект целевой зависимости обновляется, когда он уведомляется о том, что источник был изменен через интерфейс INotifyPropertyChanged.Когда привязка цели обновляется для сложных путей?

Например:

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

В текстовом поле будет меняться, чтобы правильно отражать стоимость SomeField всякий раз, когда PropertyChanged(this, new PropertyChangedEventArgs("SomeField")) вызывается из источника.

Что делать, если я использую сложный путь, как следующее:

<TextBlock Text="{Binding Path=SomeObjField.AnotherField}"/> 

Будет ли текстовое поле обновляется для PropertyChanged(this, new PropertyChangedEventArgs("SomeObjField")) на источник?

Как насчет PropertyChanged(this, new PropertyChangedEventArgs("AnotherField")) на промежуточном объекте (объект, содержащийся внутри SomeObjField)?

Исходные объекты и поля НЕ являются объектами или свойствами зависимостей! Предположим, что свойство/классы реализованы что-то вроде следующего:

public class Data : INotifyPropertyChanged 
{ 
    // INotifyPropertyChanged implementation... 

    public string SomeField 
    { 
     get { return val; } 
     set 
     { 
     val = value; 
     // fire PropertyChanged() 
     } 
    } 

    public SubData SomeObjField 
    { 
     get { return val; } 
     set 
     { 
     val = value; 
     // fire PropertyChanged() 
     } 
    } 
} 

public class SubData : INotifyPropertyChanged 
{ 
    // INotifyPropertyChanged implementation... 

    public string AnotherField 
    { 
     get { return val; } 
     set 
     { 
     val = value; 
     // fire PropertyChanged() 
     } 
    } 
} 

ответ

2

После дальнейших исследований, оказалось, что, когда любая часть сложного пути отправляет уведомление об изменении, связанное с обновлением. Таким образом, если исходный объект ИЛИ промежуточный объект изменен, привязка будет обновлена.

Я построил тестовый проект, как Джаред:

<StackPanel Name="m_panel"> 
    <TextBox IsReadOnly="True" Text="{Binding Path=SomeObjField.AnotherField }" /> 
    <TextBox x:Name="field1"/> 
    <Button Click="Button1_Click">Edit Root Object</Button> 
    <TextBox x:Name="field2"/> 
    <Button Click="Button2_Click">Edit Sub Object</Button> 
</StackPanel> 

И код позади:

public Window1() 
{ 
    InitializeComponent(); 
    m_panel.DataContext = new Data(); 
} 

private void Button1_Click(object sender, RoutedEventArgs e) 
{ 
    Data d = m_panel.DataContext as Data; 
    d.SomeObjField = new SubData(field1.Text); 
} 

private void Button2_Click(object sender, RoutedEventArgs e) 
{ 
    Data d = m_panel.DataContext as Data; 
    d.SomeObjField.AnotherField = field2.Text; 
} 

Я использую основную реализацию данных, я предоставил в этом вопросе.

0

Я не 100% уверен, что ваш спрашивать с PropertyChanged часть вопроса. Но если задействованные свойства - все свойства, поддерживаемые DependencyProperty, тогда это должно работать так, как ожидалось. Я составил следующий пример

Window1.xaml

<Window x:Class="WpfApplication1.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="Window1" Height="300" Width="300"> 
    <StackPanel Name="m_panel"> 
     <TextBlock Text="{Binding Path=SomeField}" /> 
     <TextBlock Text="{Binding Path=SomeField.AnotherField }" /> 
     <Button Click="Button_Click">Update Root Object</Button> 
     <Button Click="Button_Click_1">Update Another Field</Button> 
    </StackPanel> 
</Window> 

Window1.xaml.cs

public partial class Window1 : Window 
{ 
    public Window1() 
    { 
     InitializeComponent(); 
     m_panel.DataContext = new Class1(); 
    } 

    private void Button_Click(object sender, RoutedEventArgs e) 
    { 
     ((Class1)m_panel.DataContext).SomeField = new Class2(); 
    } 

    private void Button_Click_1(object sender, RoutedEventArgs e) 
    { 
     ((Class1)m_panel.DataContext).SomeField.AnotherField = "Updated field"; 
    } 
} 

И классы

public class Class1 : DependencyObject 
{ 
    public static DependencyProperty SomeFieldProperty = DependencyProperty.Register(
     "SomeField", 
     typeof(Class2), 
     typeof(Class1)); 

    public Class2 SomeField 
    { 
     get { return (Class2)GetValue(SomeFieldProperty); } 
     set { SetValue(SomeFieldProperty, value); } 
    } 

    public Class1() 
    { 
     SomeField = new Class2(); 
    } 
} 

public class Class2 : DependencyObject 
{ 
    public static DependencyProperty AnotherFieldProperty = DependencyProperty.Register(
     "AnotherField", 
     typeof(string), 
     typeof(Class2)); 

    public string AnotherField 
    { 
     get { return (string)GetValue(AnotherFieldProperty); } 
     set { SetValue(AnotherFieldProperty, value); } 
    } 

    public Class2() 
    { 
     AnotherField = "Default Value"; 
    } 
} 
+0

Только свойство target (TextBlock.Text в этом случае) можно считать свойством зависимости. SomeField, SomeObjField и AnotherField - нет. Если бы они были, не было бы необходимости реализовывать интерфейс INotifyPropertyChanged. –

+0

Спасибо за сообщение. Я выполнил ваш пример и создал простой тестовый проект. Я надеялся, что кто-то узнает ответ от верхней части головы. –