XAML: привязка свойства в DataTemplate
Я довольно новичок в XAML, но наслаждаюсь его изучением. Что меня действительно напрягает, так это привязка свойства к элементу DataTemplate
.
я создал простой пример WPF, чтобы (надеюсь) объяснить мою проблему.
я этот пример я пытаюсь связать Visibility
свойства CheckBox
на DataTemplate
к свойству в моей viewmodel. (Используя этот сценарий исключительно для обучения / демонстрации.)
у меня есть простая DataModel с именем Item
, но это мало значения в этом примере.
class Item : INotifyPropertyChanged
{
// Fields...
private bool _IsRequired;
private string _ItemName;
и довольно простая модель представления с именем ItemViewModel.
class ItemViewModel : INotifyPropertyChanged
{
private ObservableCollection<Item> _Items;
private bool _IsCheckBoxChecked;
private bool _IsCheckBoxVisible;
public ObservableCollection<Item> Items
{
get { return _Items; }
set { _Items = value; }
}
public bool IsCheckBoxChecked
{
get { return _IsCheckBoxChecked; }
set
{
if (_IsCheckBoxChecked == value)
return;
_IsCheckBoxChecked = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("IsCheckBoxChecked"));
PropertyChanged(this, new PropertyChangedEventArgs("IsCheckBoxVisible"));
}
}
}
public bool IsCheckBoxVisible
{
get { return !_IsCheckBoxChecked; }
set
{
if (_IsCheckBoxVisible == value)
return;
_IsCheckBoxVisible = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("IsCheckBoxVisible"));
}
(конструкторы и INotifyPropertyChanged
реализация опущена для краткости.)
элементы управления выложены в MainPage.xaml следующим образом.
<Window.Resources>
<local:VisibilityConverter x:Key="VisibilityConverter"/>
</Window.Resources>
<Window.DataContext>
<local:ItemViewModel/>
</Window.DataContext>
<Grid>
<StackPanel>
<CheckBox x:Name="checkBox" Content="Hide CheckBoxes" FontSize="14" IsChecked="{Binding IsCheckBoxChecked, Mode=TwoWay}" />
<ListView ItemsSource="{Binding Items}" HorizontalContentAlignment="Stretch" >
<ListView.ItemTemplate >
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding ItemName}"/>
<CheckBox Grid.Column="1" Visibility="{Binding IsCheckBoxVisible, Converter={StaticResource VisibilityConverter}}" >
<CheckBox.DataContext>
<local:ItemViewModel/>
</CheckBox.DataContext>
</CheckBox>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<StackPanel Orientation="Horizontal" Margin="4,4,0,0">
<TextBlock Text="IsCheckBoxVisible:"/>
<TextBlock Text="{Binding IsCheckBoxVisible}" Margin="4,0,0,0" FontWeight="Bold" />
</StackPanel >
<Button Content="Button" Visibility="{Binding IsCheckBoxVisible, Converter={StaticResource VisibilityConverter}}" Margin="4,4,4,4"/>
</StackPanel>
</Grid>
флажок "скрыть флажки" привязан к IsCheckBoxChecked
и используется для обновления IsCheckBoxVisible
. Я также добавил несколько дополнительных элементов управления ниже DataTemplate
чтобы доказать, (себе,) все завод.)
я также реализовал конвертер значений Джеффа Уилкокса. (Спасибо тебе.) http://www.jeff.wilcox.name/2008/07/visibility-type-converter/
когда я запускаю приложение, проверяя и снимая флажок "скрыть флажок", элементы управления вне DataTemplate
функция, как ожидалось, но, увы,Checkbox
внутри шаблона данных остается неизменным.
у меня был успех с:
IsVisible="{Binding IsChecked, Converter={StaticResource VisibilityConverter}, ElementName=checkBox}"
но я не просто пытаюсь имитировать другой контроль но принимайте решения, основанные на ценности.
я был бы очень признателен за любую помощь или совет, который вы можете предложить.
спасибо.
1 ответов
когда вы находитесь в DataTemplate, ваш DataContext является шаблонным объектом данных, в этом случае Item
. Таким образом, DataContext флажка в DataTemplate является Item
, а не ваши ItemViewModel
. Вы можете видеть это по вашему <TextBlock Text="{Binding ItemName}"/>
, который привязывается к собственности на Item
класса. Привязка к IsCheckBoxVisible пытается найти свойство с именем IsCheckBoxVisible на Item
.
есть несколько способов обойти это, но на сегодняшний день проще всего это сделать это:
в вашем окне (в xaml) дайте ему и x:Name. Например:
<Window [...blah blah...]
x:Name="MyWindow">
измените привязку, чтобы выглядеть так:
<CheckBox Grid.Column="1"
Visibility="{Binding DataContext.IsCheckBoxVisible, ElementName=MyWindow, Converter={StaticResource VisibilityConverter}}">
мы используем окно в качестве источника для привязки, а затем смотрим на его свойство DataContext (которое должно быть вашим ItemViewModel
, а затем снять свойство IsCheckBoxVisible.
другой вариант, если вы хотите что-то более причудливое, - использовать прокси-объект для ссылки на ваш DataContext. См.этот статья о DataContextProxy.