Когда целевая привязка обновляется для сложных путей? - PullRequest
3 голосов
/ 02 апреля 2009

При использовании привязки данных в 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 ]

2 голосов
/ 02 апреля 2009

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

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

<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 голосов
/ 02 апреля 2009

Я не уверен на 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";
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...