Порядок инициализации DependencyProperty и Binding

Имеется UserControl который содержит в себе ComboBox. В code-behind заполняются значения и задается ComboBox->SelectedValue через привязанное свойство SelectedValueLocal. Сеттер свойства SelectedValueLocal также устанавливает значение для DependencyProperty SelectedValue.

<UserControl x:Class="TestMVVM.UserControl1"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:TestMVVM"
             mc:Ignorable="d">

        <ComboBox ItemsSource="{Binding Path=Values, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}"
                  SelectedValue="{Binding Path=SelectedValueLocal, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}"/>     
</UserControl>

code-behind

public partial class UserControl1 : UserControl, INotifyPropertyChanged
{
    /*реализация INPC*/

    public List<string> Values { get; set; }

    string _selectedValueLocal;
    public string SelectedValueLocal
    {
        get { return _selectedValueLocal; }
        set 
        { 
            _selectedValueLocal = value;
            SelectedValue = _selectedValueLocal; //передача в DP
            RaisePropertyChanged();
        }
    }

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

    // Using a DependencyProperty as the backing store for SelectedValue.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty SelectedValueProperty =
        DependencyProperty.Register("SelectedValue", typeof(string), typeof(UserControl1), new PropertyMetadata(null));


    public UserControl1()
    {
        InitializeComponent();

        Values = new List<string> { "one", "two", "three" };

        SelectedValueLocal = Values.FirstOrDefault();
    }
}

Использование UserControl:

<StackPanel>           
    <local:UserControl1 SelectedValue="{Binding SelectedText, Mode=OneWayToSource}"/>     
    <TextBlock Text="{Binding SelectedText}"/> <!--ожидаю "one"-->
</StackPanel>

При запуске приложения я ожидаю в SelectedText выбранное значение у ComboBox, но привязка начинает работать только после выбора элемента в ComboBox. Я подозреваю что когда задается начальное значение DependencyProperty в code-behing, оно в это время не привязано ни к чему и соответственно значение не доходит до адресата. Есть ли способ заставить обновить привязку после запуска приложения программно?


Ответы (2 шт):

Автор решения: VladD

Строка SelectedValue = _selectedValueLocal в сеттере SelectedValueLocal затирает Binding свойства SelectedValue, заменяя его на непосредственное значение.

Попробуйте использовать вместо этого SetCurrentValue.

→ Ссылка
Автор решения: Gardes

Я подозреваю что когда задается начальное значение DependencyProperty в code-behing, оно в это время не привязано ни к чему и соответственно значение не доходит до адресата. Есть ли способ заставить обновить привязку после запуска приложения программно?

Привязки настраиваются после работы конструктора. Так, задать значение по умолчанию и быть уверенным что оно дойдет до viewmodel необходимо задавать после настройки привязки, а именно через событие Loaded:

public UserControl1()
{         
    InitializeComponent();

    Values = new List<string> { "one", "two", "three" };

    this.Loaded += UserControl1_Loaded;           
}

private void UserControl1_Loaded(object sender, RoutedEventArgs e)
{
    SetCurrentValue(SelectedValueProperty, Values.FirstOrDefault());
}
→ Ссылка