Настройка контекста данных WPF для определенного элемента управления
Я разрабатываю приложение WPF и немного пытаюсь понять некоторые детали DataContext применительно к связыванию. Мое приложение использует бизнес-объект, который определяется следующим образом:
public class MyBusinessObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(PropertyChangedEventArgs e)
{
if (PropertyChanged != null)
{
PropertyChanged(this, e);
}
}
// enumerations for some properties
public enum MyEnumValues
{
[Description("New York")]
NewYork,
[Description("Chicago")]
Chicago,
[Description("Los Angeles")]
LosAngeles
}
// an example property
private string _myPropertyName;
public string MyPropertyName
{
get { return _myPropertyName; }
set
{
if (_myPropertyName == value)
{
return;
}
_myPropertyName = value;
OnPropertyChanged(new PropertyChangedEventArgs("MyPropertyName"));
}
}
// another example property
private MyEnumValues _myEnumPropertyName;
public MyEnumValues MyEnumPropertyName
{
get { return _myEnumPropertyName; }
set
{
if (_myEnumPropertyName== value)
{
return;
}
_myEnumPropertyName= value;
OnPropertyChanged(new PropertyChangedEventArgs("MyEnumPropertyName"));
}
}
// example list property of type Widget
public List<Widget> MyWidgets { get; set; }
// constructor
public MyBusinessObject()
{
// initialize list of widgets
MyWidgets = new List<Widget>();
// add 10 widgets to the list
for (int i = 1; i <= 10; i++)
{
MyWidgets.Add(new Widget());
}
// set default settings
this.MyPropertyName = string.empty;
}
}
Как видите, у меня есть некоторые свойства, которые объявлены в этом классе, одним из которых является список виджетов. Сам класс Widget также реализует INotifyPropertyChanged и предоставляет около 30 свойств.
Мой пользовательский интерфейс имеет поле со списком, который связан с моим списком виджетов, как это:
MyBusinessObject myBusinessObject = new MyBusinessObject();
public MainWindow()
{
InitializeComponent();
this.DataContext = myBusinessObject;
selectedWidgetComboBox.ItemsSource = myBusinessObject.MyWidgets;
selectedWidgetComboBox.DisplayMemberPath = "WidgetName";
selectedWidgetComboBox.SelectedValuePath = "WidgetName";
}
Большинство элементов управления в моем пользовательском интерфейсе используются для отображения свойств виджета. Когда мой пользователь выбирает виджет из выпадающего списка, я хочу, чтобы эти элементы управления отображали свойства выбранного виджета. В настоящее время я достигаю этого поведения, обновляя DataContext моего окна в обработчике событий SelectionChanged моего комбинированного списка следующим образом:
private void selectedWidgetComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
this.DataContext = selectedWidgetComboBox.SelectedItem;
}
Это позволяет мне привязать мои элементы управления к соответствующему свойству Widget, например так:
<TextBox Text="{Binding WidgetColor}"></TextBox>
Однако не все элементы управления в моем пользовательском интерфейсе используются для отображения свойств виджета. Некоторые элементы управления должны отображать свойства из MyBusinessObject (например, определенное выше MyPropertyName). В этом сценарии я не могу просто сказать:
<TextBox Text="{Binding MyPropertyName}"></TextBox>
... потому что DataContext окна указывает на выбранный виджет вместо MyBusinessObject. Может кто-нибудь сказать мне, как я устанавливаю DataContext для определенного элемента управления (в XAML), чтобы ссылаться на тот факт, что MyPropertyName является свойством MyBusinessObject? Спасибо!
2 ответа
Вместо того, чтобы изменять DataContext вашего окна, вы должны добавить свойство в ваш класс MyBusinessObject, например:
private Widget _selectedWidget;
public Widget SelectedWidget
{
get { return _selectedWidget; }
set
{
if (_selectedWidget == value)
{
return;
}
_selectedWidget = value;
OnPropertyChanged(new PropertyChangedEventArgs("SelectedWidget"));
}
}
Затем привяжите SelectedWidget к свойству SelectedItem вашего комбинированного списка. Везде, где вам нужно использовать свойства виджета, вы можете сделать это:
<TextBox Text="{Binding Path=SelectedWidget.WidgetColor}"></TextBox>
Пытаться
<TextBox Text="{Binding MyBusinessObject.MyPropertyName}"></TextBox>
это работает, если MyBusinessObject является текстовым полем текстового поля, а MyPropertyName является свойством MyBusinessObject.
Также, вот хорошая статья для уточнения связывания
надеюсь это поможет
РЕДАКТИРОВАТЬ 1:
используйте относительную привязку как это:
text="{Binding DataContext.MyPropertyName, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TypeOfControl}}}"
Таким образом, привязка relatve позволяет вам искать визуальное дерево в другом элементе пользовательского интерфейса и использовать его текст данных. Я хотел бы рассмотреть оборачивать содержимое вашего окна в сетку. и смочите данные Windows-контекста для бизнес-объекта и сетки данных-контекста для виджета. Таким образом, вы всегда можете использовать текст данных родительского окна через реальную привязку источника.
поэтому используйте следующее, если datacontext вашего окна является вашим бизнес-объектом
text="{Binding DataContext.MyPropertyName, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}"