Привязка WPF к переменной / DependencyProperty - PullRequest
6 голосов
/ 28 декабря 2010

Я играю с WPF Binding и переменными. Видимо, можно связать только DependencyProperties. Я придумал следующее, которое прекрасно работает: Файл с выделенным кодом:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    public string Test
    {
        get { return (string)this.GetValue(TestProperty); }
        set { this.SetValue(TestProperty, value); }
        //set { this.SetValue(TestProperty, "BBB"); }
    }
    public static readonly DependencyProperty TestProperty = DependencyProperty.Register(
      "Test", typeof(string), typeof(MainWindow), new PropertyMetadata("CCC"));

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        MessageBox.Show(Test);
        Test = "AAA";
        MessageBox.Show(Test);
    }
}

XAML:

<Window x:Class="WpfApplication3.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase"
    Title="MainWindow" Height="350" Width="525"
    DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid>
    <TextBox Height="31" HorizontalAlignment="Left" Margin="84,86,0,0" Name="textBox1" VerticalAlignment="Top" Width="152" 
             Text="{Binding Test, Mode=TwoWay, diag:PresentationTraceSources.TraceLevel=High}"/>
    <Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="320,85,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click" />
    <TextBox Height="31" HorizontalAlignment="Left" Margin="84,138,0,0" Name="textBox2" Text="{Binding Test, Mode=TwoWay}" VerticalAlignment="Top" Width="152" />
</Grid>

Два текстовых поля обновляют друг друга. И Кнопка устанавливает их на «AAA».

Но теперь я заменил функцию Setter на закомментированную (имитирующую некоторые манипуляции с данным значением). Я ожидаю, что всякий раз, когда значение свойства изменяется, оно сбрасывается на «BBB». Это происходит при нажатии кнопки, то есть при установке свойства в коде. Но это по какой-то причине не влияет на привязки WPF, то есть вы можете изменить содержимое TextBox и, следовательно, его свойство, но, очевидно, метод Setter никогда не вызывается. Интересно, почему это так, и как можно достичь ожидаемого поведения?

Ответы [ 2 ]

14 голосов
/ 28 декабря 2010

Оболочка свойства CLR для свойства зависимости никогда не вызывается, поэтому вам никогда не следует размещать там дополнительную логику. Всякий раз, когда вам нужна дополнительная логика при смене DP, вы должны использовать свойство callback для измененного свойства.

В вашем случае ..

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

public static readonly DependencyProperty TestProperty =
    DependencyProperty.Register("Test",
    typeof(string),
    typeof(MainWindow),
    new PropertyMetadata("CCC", TestPropertyChanged));

private static void TestPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
{
    MainWindow mainWindow = source as MainWindow;
    string newValue = e.NewValue as string;
    // Do additional logic
}
2 голосов
/ 28 декабря 2010

Ваше изменение не повлияет на привязку, поскольку XAML будет вызывать SetValue напрямую, а не вызывать ваш метод установки свойств. Так работает система свойств зависимостей. Когда свойство зависимости регистрируется, можно указать значение по умолчанию. Это значение возвращается из GetValue и является значением по умолчанию для вашего свойства.

Проверьте ссылку ниже и прочитайте пост Роберта Россни, чтобы получить объективный обзор

WPF: Чем отличается свойство зависимости от обычного свойства CLR?

также не пропустите

http://msdn.microsoft.com/en-us/library/ms753358.aspx

и

http://msdn.microsoft.com/en-us/library/ms752914.aspx

Также обратите внимание, что в отличие от обычных свойств CLR, любая пользовательская логика, которую вы пишете в установщике, не будет выполняться в свойствах зависимости, вместо этого вы должны использовать механизм PropertyChangedCallback

http://blogs.msdn.com/b/delay/archive/2010/03/23/do-one-thing-and-do-it-well-tip-the-clr-wrapper-for-a-dependencyproperty-should-do-its-job-and-nothing-more.aspx

...