Привязка данных WPF к свойству в UserControl с помощью ViewModel - PullRequest
0 голосов
/ 21 октября 2018

Я пытаюсь встроить некоторую функциональность в повторно используемый UserControl в моем приложении в стиле MVVM.Фреймворк MVVM на этом этапе в большинстве случаев выполняется вручную, поскольку приложение WPF начало свою жизнь, будучи написанным в основном как приложение WinForms.

Созданный мной UserControl - это просто ComboBox в пользовательском интерфейсе с некоторыми данными.загрузка выполнена ViewModel.Все ViewModel в приложении загружаются локатором ViewModel, поэтому мне не нужно внедрять ViewModels в ViewModels, это работает везде в приложении, поэтому я не думаю, что это проблема здесь:

<UserControl DataContext="{Binding Common_PopulationSelector,Source={StaticResource ViewModelLocator}}">
    <ComboBox ItemsSource="{Binding Population}" SelectedItem="{Binding SelectedPopulation}" DisplayMemberPath="PopulationName" IsEditable="False"></ComboBox>
</UserControl>

Отдельные биты ViewModel:

public class PopulationSelectorViewModel : BaseViewModel
{
    public override async void OnCreate()
    {
        //Called by the ViewModelLocator when this isntance is created
        //Data loading done here, puts a list of Populations into the Populations collection
        //SelectedPopulation gets set to a default value here
    }

    public ObservableCollection<Population> Populations { get; }

    private Population _selectedPopulation;
    public Population SelectedPopulation
    {
        get => _selectedPopulation;
        set
        {
            OnPropertyChanged(ref _selectedPopulation, value);
            InvokePropertyChanged(nameof(PopulationId));
        }
    }

     public int PopulationId
     {
        get => _selectedPopulation?.PopulationID ?? 0;
        set
        {
            SelectedPopulation= Populations.FirstOrDefault(r => r.PopulationID == value) ?? _selectedPopulation;
            InvokePropertyChanged(nameof(PopulationId));
        }
    }
}

OnPropertyChanged и InvokePropertyChanged работают в другом месте приложения и просто обрабатывают работу с сантехникой вокруг INotifyPropertyChanged

Эти битыработают нормально, данные загружаются, SelectedPopulation изменяется вместе со свойством PopulationId.

Суть проблемы заключается в представлении PopulationId как свойства XAML, с которым могут связываться потребители UserControl.Этот элемент управления используется следующим образом:

<views:PopulationSelector PopulationId="{Binding Path=DataContext.PopulationId, RelativeSource={RelativeSource AncestorType={x:Type local:SearchParameters}}, Mode=TwoWay}" />

SearchParameters - это UserControl, содержащий селектор.Чтобы выставить PopulationId, у меня есть это в коде XAML:

public partial class PopulationSelector : UserControl
{
    public PopulationSelector()
    {
        InitializeComponent();
        this.SetBinding(PopulationIdProperty, new Binding("PopulationId") { Mode = BindingMode.TwoWay });
    }

    public static readonly DependencyProperty PopulationIdProperty = DependencyProperty.Register(
        "PopulationId", typeof(int), typeof(PopulationSelector), new PropertyMetadata(-1));

    public int PopulationId
    {
        get
        {

            return (int)GetValue(PopulationIdProperty);
        }
        set
        {
            var oldValue = (int)GetValue(PopulationIdProperty);
            if (oldValue != value) SetValue(PopulationIdProperty, value);
        }
    }
}

Это, очевидно, где происходит разрыв.Я устанавливаю значение по умолчанию для DependencyProperty здесь равным -1, и оно меняется на 0, поэтому связывание с UserControl, потребляющим это, похоже, работает.Но свойство PopulationId WPF никогда не обновляется из ViewModel.

Итак, короче (это так давно, когда я пытался сделать это во время записи): я пытаюсь привязаться к WPFсвойство пользовательского элемента управления, привязанное к ViewModel для этого элемента управления.Привязка к пользовательскому элементу управления, по-видимому, работает, а привязка модели представления к пользовательскому элементу управления - нет.Как я могу заставить WPF делать то, что я хочу?

Редактировать:

Я внес несколько изменений в мои фрагменты кода, которые приводят его в соответствие с моимнедавние попытки сделать эту работу

  • Обновлен сеттер в codebehind для usercontrol, чтобы он соответствовал ссылке, которую я использовал, а именно: DependencyProperty представления Twoway-bind для свойства viewmodel?
  • Обновлена ​​привязка между свойством XAML и ViewModel.При публикации я немного упростил код (до привязки к свойству вне SelectedPopulation), и опубликованный код не работал.Я добавил сеттер в PopulationId для модели представления, чтобы двусторонняя привязка работала правильно

Сегодня утром немного поиграв с точками останова, вот что я установил:

  • Вызывается установщик для SelectedPopulation в ViewModel, поэтому связывание между ComboBox и ViewModel в порядке.
  • Получатель для PopulationId в ViewModel никогда не вызывается
  • Получатель или установщик дляPopulationId в коде UserControl никогда не вызывается
  • Установщик для PopulationId в представлении, использующем этот пользовательский элемент управления, никогда не вызывается

Я также только что попробовал этот ответ: https://stackoverflow.com/a/21851139/117651 где привязка между ViewModel и свойством XAML выполняется в XAML.Вызывается метод получения в ViewModel, а свойство PopulationId XAML показывает ожидаемое значение в проводнике свойств при работе в отладчике.Однако привязка между потребителем и свойством XAML не работает, и значение в ViewModel остается равным 0.

У меня также есть PresentationTraceSources, подключенное к nlog, и в журналах нет жалобС уважением к обязательным выражениям.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...