Sup*_*JMN 6 .net c# wpf xaml uwp
给定一个任意的ItemsControl,比如a ListView,我想从内部设置一个绑定ItemsTemplate到托管容器.我怎么能这么容易呢?例如,在WPF中我们可以在里面使用它ItemTemplate
<ListView.ItemTemplate>
<DataTemplate>
<SomeControl Property="{Binding Path=TargetProperty, RelativeSouce={RelativeSource FindAncestor, AncestorType={x:Type MyContainer}}}" />
</DataTemplate>
<ListView.ItemTemplate>
Run Code Online (Sandbox Code Playgroud)
在此示例中(为WPF)的结合会之间设定Property在SomeControl和TargetProperty的ListViewItem(隐含的,因为它会被动态生成ListView来承载每个其项).
我们怎样才能在UWP中实现同样的目标?
我想要一些MVVM友好的东西.可能附加属性或交互行为.
注意:此答案基于 WPF,UWP 可能需要进行一些更改。
基本上有两种情况需要考虑:
让我们假设这两种情况都有一个自定义的列表视图:
public class MyListView : ListView
{
protected override DependencyObject GetContainerForItemOverride()
{
return new DesignerItem();
}
protected override bool IsItemItsOwnContainerOverride(object item)
{
return item is DesignerItem;
}
}
public class DesignerItem : ListViewItem
{
public bool IsEditing
{
get { return (bool)GetValue(IsEditingProperty); }
set { SetValue(IsEditingProperty, value); }
}
public static readonly DependencyProperty IsEditingProperty =
DependencyProperty.Register("IsEditing", typeof(bool), typeof(DesignerItem));
}
Run Code Online (Sandbox Code Playgroud)
在情况 1 中,您可以使用将ItemContainerStyleviewmodel 属性与绑定链接起来,然后在数据模板内绑定相同的属性
class MyData
{
public bool IsEditing { get; set; } // also need to implement INotifyPropertyChanged here!
}
Run Code Online (Sandbox Code Playgroud)
XAML:
<local:MyListView ItemsSource="{Binding Source={StaticResource items}}">
<local:MyListView.ItemContainerStyle>
<Style TargetType="{x:Type local:DesignerItem}">
<Setter Property="IsEditing" Value="{Binding IsEditing,Mode=TwoWay}"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
</local:MyListView.ItemContainerStyle>
<local:MyListView.ItemTemplate>
<DataTemplate>
<Border Background="Red" Margin="5" Padding="5">
<CheckBox IsChecked="{Binding IsEditing}"/>
</Border>
</DataTemplate>
</local:MyListView.ItemTemplate>
</local:MyListView>
Run Code Online (Sandbox Code Playgroud)
在情况 2 中,您似乎并没有真正拥有数据驱动的属性,因此,您的属性的效果应反映在控件 ( ControlTemplate) 内。
在以下示例中,工具栏根据属性变得可见IsEditing。切换按钮可用于控制属性,ItemTemplate用作工具栏和按钮旁边的内部元素,它对状态一无所知IsEditing:
<local:MyListView ItemsSource="{Binding Source={StaticResource items}}">
<local:MyListView.ItemContainerStyle>
<Style TargetType="{x:Type local:DesignerItem}">
<Setter Property="IsEditing" Value="{Binding IsEditing,Mode=TwoWay}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:DesignerItem}">
<DockPanel>
<ToggleButton DockPanel.Dock="Right" Margin="5" VerticalAlignment="Top" IsChecked="{Binding IsEditing,RelativeSource={RelativeSource TemplatedParent},Mode=TwoWay}" Content="Edit"/>
<!--Toolbar is something control related, rather than data related-->
<ToolBar x:Name="MyToolBar" DockPanel.Dock="Top" Visibility="Collapsed">
<Button Content="Tool"/>
</ToolBar>
<ContentPresenter ContentSource="Content"/>
</DockPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsEditing" Value="True">
<Setter TargetName="MyToolBar" Property="Visibility" Value="Visible"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</local:MyListView.ItemContainerStyle>
<local:MyListView.ItemTemplate>
<DataTemplate>
<Border Background="Red" Margin="5" Padding="5">
<TextBlock Text="Hello World"/>
</Border>
</DataTemplate>
</local:MyListView.ItemTemplate>
</local:MyListView>
Run Code Online (Sandbox Code Playgroud)
为了获得更好的控件模板,您可以选择使用 Blend 并从完整ListViewItem模板开始创建控件模板,然后将更改编辑到其中。
如果您的 DesignerItem 通常具有特定的增强外观,请考虑使用Themes/Generic.xaml适当的默认样式对其进行设计。
正如所评论的,您可以为编辑模式提供单独的数据模板。为此,请向MyListView和 中添加一个属性DesignerItem,并使用它MyListView.PrepareContainerForItemOverride(...)来传输模板。
为了应用模板而不需要绑定,您可以使用基于的Setter.Value值强制。DesignerItem.ContentTemplateIsEditing
public class MyListView : ListView
{
protected override DependencyObject GetContainerForItemOverride()
{
return new DesignerItem();
}
protected override bool IsItemItsOwnContainerOverride(object item)
{
return item is DesignerItem;
}
protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
{
base.PrepareContainerForItemOverride(element, item);
var elem = element as DesignerItem;
elem.ContentEditTemplate = ItemEditTemplate;
}
public DataTemplate ItemEditTemplate
{
get { return (DataTemplate)GetValue(ItemEditTemplateProperty); }
set { SetValue(ItemEditTemplateProperty, value); }
}
public static readonly DependencyProperty ItemEditTemplateProperty =
DependencyProperty.Register("ItemEditTemplate", typeof(DataTemplate), typeof(MyListView));
}
public class DesignerItem : ListViewItem
{
static DesignerItem()
{
ContentTemplateProperty.OverrideMetadata(typeof(DesignerItem), new FrameworkPropertyMetadata(
null, new CoerceValueCallback(CoerceContentTemplate)));
}
private static object CoerceContentTemplate(DependencyObject d, object baseValue)
{
var self = d as DesignerItem;
if (self != null && self.IsEditing)
{
return self.ContentEditTemplate;
}
return baseValue;
}
private static void OnIsEditingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
d.CoerceValue(ContentTemplateProperty);
}
public bool IsEditing
{
get { return (bool)GetValue(IsEditingProperty); }
set { SetValue(IsEditingProperty, value); }
}
public static readonly DependencyProperty IsEditingProperty =
DependencyProperty.Register("IsEditing", typeof(bool), typeof(DesignerItem), new FrameworkPropertyMetadata(new PropertyChangedCallback(OnIsEditingChanged)));
public DataTemplate ContentEditTemplate
{
get { return (DataTemplate)GetValue(ContentEditTemplateProperty); }
set { SetValue(ContentEditTemplateProperty, value); }
}
// Using a DependencyProperty as the backing store for ContentEditTemplate. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ContentEditTemplateProperty =
DependencyProperty.Register("ContentEditTemplate", typeof(DataTemplate), typeof(DesignerItem));
}
Run Code Online (Sandbox Code Playgroud)
ListViewItem.IsSelected请注意,为了更简单的示例,我将通过一些触发器激活“编辑”模式:
<local:MyListView ItemsSource="{Binding Source={StaticResource items}}">
<local:MyListView.ItemContainerStyle>
<Style TargetType="{x:Type local:DesignerItem}">
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="IsEditing" Value="True"/>
</Trigger>
</Style.Triggers>
</Style>
</local:MyListView.ItemContainerStyle>
<local:MyListView.ItemTemplate>
<DataTemplate>
<Border Background="Red" Margin="5" Padding="5">
<TextBlock Text="Hello World"/>
</Border>
</DataTemplate>
</local:MyListView.ItemTemplate>
<local:MyListView.ItemEditTemplate>
<DataTemplate>
<Border Background="Green" Margin="5" Padding="5">
<TextBlock Text="Hello World"/>
</Border>
</DataTemplate>
</local:MyListView.ItemEditTemplate>
</local:MyListView>
Run Code Online (Sandbox Code Playgroud)
预期行为:所选项目变为可编辑状态,获得local:MyListView.ItemEditTemplate(绿色)而不是默认模板(红色)
| 归档时间: |
|
| 查看次数: |
1232 次 |
| 最近记录: |