Я пытаюсь правильно выполнить следующее.У меня есть UserControl (ProgramView).У него есть модель представления (ProgramViewViewModel).ProgramView используется как дочерний элемент управления в окне (ProgramWindow).ProgramWindow имеет открытое свойство ProgramId, поэтому потребитель окна может указать желаемую Программу (объект данных) для отображения.ProgramView имеет свойство ProgramId, так как его основной задачей является отображение этих данных.ProgramWindow - это чуть больше, чем окно-обертка для этого пользовательского элемента управления.
ProgramViewViewModel также имеет свойство ProgramId.Изменения в этом свойстве вытесняют работу модели представления, которая выходит из модели представления с использованием других свойств, к которым может привязываться ProgramView.
Я пытаюсь скрыть операцию модели представления отПотребитель ProgramView и ProgramWindow.
Этот ProgramId должен быть связан через все эти слои.Изменения в ProgramWindow.ProgramId должны передаваться в ProgramView.ProgramId, а затем в ProgramViewViewModel.ProgramId.Я не могу понять, как правильно это реализовать.
Мой нынешний подход - использовать ProgramId во всех трех классах как DP.В окне я мог бы представить, что экземпляр ProgramView создается следующим образом:
<local:ProgramView ProgramId="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:ProgramWindow}}, Path=ProgramId}" />
Кажется, это действительно работает.В ProgramView я получаю измененные события для свойства, и они, кажется, имеют правильное значение.Кажется, что FindAncestor работает правильно.
Как тогда синхронизировать свойство ProgramViewViewModel.ProgramId?Я вижу два пути.Одним из способов было бы установить Binding для самого экземпляра ProgramViewViewModel, также использовать FindAncestor и найти ProgramId в ProgramViewViewModel. У этого есть два недостатка.Требуется ProgramViewViewModel для отображения ProgramId как свойства зависимости.Я бы предпочел избежать этого, но это может быть приемлемым.В любом случае, я не могу выполнить это в XAML.
<local:View.DataContext>
<local:ProgramViewViewModel
ProgramId="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:ProgramView}}, Path=ProgramId}" />
</local:View.DataContext>
Это не работает.Похоже, что я не могу ввести связывающее выражение в экземпляре экземпляра.FindAncestor сообщает, что не может найти ProgramView.Моя теория заключается в том, что экземпляр находится за пределами логического дерева и, следовательно, не может перейти к своему родителю.
Второй вариант, который имеет больше смысла, - это привязка свойства ProgramView.ProgramId к «ProgramId»в DataContext).Я не могу этого сделать, потому что не могу понять, как указать выражение привязки для свойства, определенного в коде.требуется в XAML, но на самом деле существует тип ProgramId.Я не могу понять, как задать это свойство.
Если я вручную (в программном обеспечении ProgramView) создаю экземпляр Binding и вызываю SetBinding (ProgramIdProperty, binding), значение больше не попадает в само представление.Я считаю, что это потому, что я только что заменил привязку на ProgramView.ProgramId, который был ранее установлен ProgramWindow.Одна привязка для каждого свойства?
Мои оставшиеся идеи - предоставить ДВА свойства ProgramId в ProgramView.Один привязан к DataContext, другой общедоступен для привязки потребителем (ProgramWindow), а затем пишет обработчики OnValueChanged, которые синхронизируют два.Это похоже на взлом.Другой - вручную следить за изменениями в ProgramView.ProgramId и ProgramView.DataContext внутри кода программы ProgramView и самому распространять значение.Ни одна из этих идей не кажется идеальной.
Я ищу другие предложения.