TwoWay Binding не работает через DependencyProperty

244
09 декабря 2016, 08:46

При изменении свойства через TwoWay binding не производится работа с переменной, только со свойством зависимости.

Отметил в коде комментариями нужные места.

Пути обхода я знаю (самый явный - через PropertyChanged), но неужели всё так плохо?

Вопрос, собственно, в том, как просто сделать двухсторонний binding?

Проект здесь: https://yadi.sk/d/ioEe0PZ2v7pEC

MainWindow.xaml

<Window x:Class="SampleProject.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Sample" Height="100" Width="500">
    <UniformGrid Columns="1" Margin="5">
        <!-- Привязка на следующей строке НЕ вызовет setter переменной SliderValue -->
        <Slider Value="{Binding SliderValue,
                        RelativeSource={RelativeSource AncestorType=Window}}"/>
        <TextBlock Text="{Binding TextValue,
                        RelativeSource={RelativeSource AncestorType=Window}}"/>
    </UniformGrid>
</Window>

MainWindow.xaml.cs

using System.Windows;
namespace SampleProject
{
    public partial class MainWindow
    {
        public MainWindow()
        {
            InitializeComponent();
            SliderValue = 3.123456789; // <<== Это вызовет setter переменной SliderValue
        }
        // ==>> TextBlock.Text
        public string TextValue
        {
            get { return (string)GetValue(_propTextValue); }
            set { SetValue(_propTextValue, value); }
        }
        public static readonly DependencyProperty _propTextValue =
            DependencyProperty.Register("TextValue", typeof(string),
            typeof(MainWindow),
            new FrameworkPropertyMetadata("Ожидание значения..."));
        // ==>> Slider.Value
        public double SliderValue
        {
            get
            { return (double) GetValue(_propSliderValue); }
            set
            {
                TextValue = value.ToString();
                SetValue(_propSliderValue, value);
            }
        }
        public static readonly DependencyProperty _propSliderValue =
            DependencyProperty.Register("SliderValue", typeof(double),
            typeof(MainWindow),
            new FrameworkPropertyMetadata(5.0, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
    }
}
Answer 1

Вы нарушили контракт для DependencyProperty: ваши static-поля должны называться TextValueProperty и SliderValueProperty соответственно (а не _propTextValue и _propSliderValue).

Переименуйте.

Кроме того, вы почему-то надеетесь, что ваш setter будет вызываться WPF-фреймворком. Нет, это тоже не гарантировано. Связывать dependency property нужно через property change callback:

public double SliderValue
{
    get { return (double) GetValue(SliderValueProperty); }
    set { SetValue(SliderValueProperty, value); }
}
public static readonly DependencyProperty SliderValueProperty =
    DependencyProperty.Register(
        "SliderValue",
        typeof(double),
        typeof(MainWindow),
        new FrameworkPropertyMetadata(
            5.0,
            FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
            OnSliderChange));
static void OnSliderChange(DependencyObject o, DependencyPropertyChangedEventArgs args)
{
    var self = (MainWindow)o;
    self.TextValue = args.NewValue.ToString();
}

Ну или немного проще:

public double SliderValue
{
    get { return (double) GetValue(SliderValueProperty); }
    set { SetValue(SliderValueProperty, value); }
}
public static readonly DependencyProperty SliderValueProperty =
    DependencyProperty.Register(
        "SliderValue",
        typeof(double),
        typeof(MainWindow),
        new FrameworkPropertyMetadata(
            5.0,
            FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
            (o, args) => o.SetValue(TextValueProperty, args.NewValue.ToString()));
READ ALSO
Хочу отображать блокнот на Локскрине Windows 10

Хочу отображать блокнот на Локскрине Windows 10

Хочу, чтобы на локскрине (экране блокировки) отображался блокнотикКод обваливается на этой строчке:

212
Перебор всех control в winforms

Перебор всех control в winforms

Мне в цикле надо перебрать абсолютно все control'ы в форме (в том числе и их дети)С пом

252
След от кнопки(полоса за кнопкой)

След от кнопки(полоса за кнопкой)

Друзья, написал программу "Гонки кнопок", подскажите, что сделать, чтобы за каждой кнопкой шел след(линия):

263
mimekit IMAP - Proxy C#

mimekit IMAP - Proxy C#

Доброго времени суток, я использую библиотеку mimekit, для работы с IMAPНо переискав весь интернет, я ничего толком и не нашел

1275