[英]XAML TemplateBinding within a DataTemplate
I'm creating a templated control for a UWP app, and I've hit a snag when trying to bind within a nested DataTemplate. 我正在为UWP应用创建模板化控件,在尝试绑定到嵌套DataTemplate中时遇到了障碍。 Here's my control XAML in Themes/Generic.xaml:
这是我在Themes / Generic.xaml中的控件XAML:
<Style TargetType="local:EnhancedListView">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:EnhancedListView">
<Grid HorizontalAlignment="Stretch">
<Grid.Resources>
<DataTemplate x:Key="ListViewTemplate">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<CheckBox Visibility="{Binding RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource BooleanToVisibilityConverter}, Path=IsCheckModeEnabled}" Grid.Column="0" />
<TextBlock Text="{Binding}" Grid.Column="1" />
</Grid>
</DataTemplate>
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<CheckBox Visibility="{Binding RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource BooleanToVisibilityConverter}, Path=IsCheckModeEnabled}" Grid.Row="0">Hello</CheckBox>
<ListView Grid.Row="1" ItemsSource="{TemplateBinding ItemsSource}" ItemTemplate="{StaticResource ListViewTemplate}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Here's my actual control/converter: 这是我的实际控制/转换器:
public class EnhancedListView : Control
{
public EnhancedListView()
{
DefaultStyleKey = typeof(EnhancedListView);
}
public object ItemsSource
{
get { return GetValue(ItemsSourceProperty); }
set { SetValue(ItemsSourceProperty, value); }
}
public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register("ItemsSource", typeof(object), typeof(EnhancedListView), new PropertyMetadata(null));
public bool IsCheckModeEnabled
{
get { return (bool)GetValue(IsCheckModeEnabledProperty); }
set { SetValue(IsCheckModeEnabledProperty, value); }
}
public static readonly DependencyProperty IsCheckModeEnabledProperty = DependencyProperty.Register("IsCheckModeEnabled", typeof(bool), typeof(EnhancedListView), new PropertyMetadata(null));
}
public class BooleanToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
return (bool)value ? Visibility.Visible : Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotSupportedException();
}
}
Here's the MainPage.xaml: 这是MainPage.xaml:
<local:EnhancedListView IsCheckModeEnabled="False" x:Name="ctlListView">
</local:EnhancedListView>
And finally, my MainPage.xaml.cs: 最后,我的MainPage.xaml.cs:
public MainPage()
{
this.InitializeComponent();
ctlListView.ItemsSource = new List<string> { "Item 1", "Item 2" };
}
As I would expect, when the page loads, the first checkbox is hidden because IsCheckModeEnabled is false, but all the checkboxes nested within the DataTemplate are still visible. 如我所料,页面加载时,第一个复选框被隐藏,因为IsCheckModeEnabled为false,但是嵌套在DataTemplate中的所有复选框仍然可见。
I've tried wrapping this into a StaticResource as suggested here , but it doesn't work with some complex types, such as nesting another DataTemplate within my DataTemplate. 我已尝试按照此处的建议将其包装到StaticResource中,但是它不适用于某些复杂类型,例如在DataTemplate中嵌套另一个DataTemplate。
I'm certain the binding isn't quite right on the Visibility property here: 我确定这里的Visibility属性的绑定不正确:
<CheckBox Visibility="{Binding RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource BooleanToVisibilityConverter}, Path=IsCheckModeEnabled}" Grid.Column="0" />
Thanks for your help! 谢谢你的帮助!
Just a guess but how about this: 只是一个猜测,但是呢:
<CheckBox Visibility="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=local:EnhancedListView}, Converter={StaticResource BooleanToVisibilityConverter}, Path=IsCheckModeEnabled}" DataContext="{Binding}" Grid.Column="0" />
btw: man this is convoluted... 顺便说一句:这真令人费解...
I believe I found a "cleaner" solution that works. 我相信我找到了一个可行的“更清洁”的解决方案。 I created a new
EnhancedListViewItem
class which can mimic the properties on the EnhancedListView.
我创建了一个新的
EnhancedListViewItem
类,该类可以模拟EnhancedListView.
上的属性EnhancedListView.
Then I assign and style that EnhancedListViewItem
independently from the parent EnhancedListView.
然后我给你和风格,
EnhancedListViewItem
独立于母公司EnhancedListView.
Here's my updated Generic.xaml: 这是我更新的Generic.xaml:
<Style TargetType="local:EnhancedListView">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:EnhancedListView">
<Grid HorizontalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<CheckBox Visibility="{Binding RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource BooleanToVisibilityConverter}, Path=IsCheckModeEnabled}" Grid.Column="0" />
<ListView Grid.Row="1" ItemsSource="{TemplateBinding ItemsSource}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="local:EnhancedListViewDataItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:EnhancedListViewDataItem">
<Grid HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<CheckBox Visibility="{Binding RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource BooleanToVisibilityConverter}, Path=IsCheckModeEnabled}" Grid.Column="0" />
<TextBlock Text="{Binding}" Grid.Column="1" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And here's my updated code behind for the controls: 这是我后面的控件更新代码:
public class EnhancedListView : Control, INotifyPropertyChanged
{
public EnhancedListView()
{
DefaultStyleKey = typeof(EnhancedListView);
}
public event PropertyChangedEventHandler PropertyChanged;
public object ItemsSource
{
get { return GetValue(ItemsSourceProperty); }
set
{
var boundItems = new List<EnhancedListViewDataItem>();
foreach (var obj in (List<string>)value)
{
boundItems.Add(new EnhancedListViewDataItem(this)
{
DataContext = obj
});
}
SetValue(ItemsSourceProperty, boundItems);
}
}
public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register("ItemsSource", typeof(object), typeof(EnhancedListView), new PropertyMetadata(null));
public bool IsCheckModeEnabled
{
get { return (bool)GetValue(IsCheckModeEnabledProperty); }
set
{
SetValue(IsCheckModeEnabledProperty, value);
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("IsCheckModeEnabled"));
}
}
public static readonly DependencyProperty IsCheckModeEnabledProperty = DependencyProperty.Register("IsCheckModeEnabled", typeof(bool), typeof(EnhancedListView), new PropertyMetadata(null));
}
public class EnhancedListViewDataItem : ListViewItem
{
public EnhancedListViewDataItem(EnhancedListView listView)
{
_listView = listView;
_listView.PropertyChanged += _listView_PropertyChanged;
DefaultStyleKey = typeof(EnhancedListViewDataItem);
}
private readonly EnhancedListView _listView;
private void _listView_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
IsCheckModeEnabled = _listView.IsCheckModeEnabled;
}
public bool IsCheckModeEnabled
{
get { return (bool)GetValue(IsCheckModeEnabledProperty); }
set { SetValue(IsCheckModeEnabledProperty, value); }
}
public static readonly DependencyProperty IsCheckModeEnabledProperty = DependencyProperty.Register("IsCheckModeEnabled", typeof(bool), typeof(EnhancedListViewDataItem), new PropertyMetadata(null));
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.