如何在此 ControlTemplate 中进行绑定?
Posted
技术标签:
【中文标题】如何在此 ControlTemplate 中进行绑定?【英文标题】:How can I bind inside this ControlTemplate? 【发布时间】:2015-11-17 20:39:57 【问题描述】:我有一个ListView
,里面装满了List<MyListItem>
,我需要使用ControlTemplate
才能在选择项目时更改效果。现在我遇到了Binding MyProperty
在ControlTemplate
内部不起作用的问题。如何访问模板内MyListItem
的属性?
我的 XAML 看起来像这样(简化):
<ListView
Name="ListView"
Grid.Column="1"
IsSwipeEnabled="False">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListViewItem">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
</VisualStateGroup>
<VisualStateGroup x:Name="SelectionStates">
<VisualState x:Name="Unselected">
<Storyboard>
<ColorAnimation Duration="0" Storyboard.TargetName="myColoredText" Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)" To="Orange"/>
</Storyboard>
</VisualState>
<VisualState x:Name="SelectedUnfocused">
<Storyboard>
<ColorAnimation Duration="0" Storyboard.TargetName="myColoredText" Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)" To="Red"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<!-- Here I have my custom layout, removed for readability -->
<TextBlock
Name="myColoredText"
Foreground="Green"
Text="Binding MyProperty"/><!-- This does not work -->
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
</ListView>
这是这个 XAML 背后的类:
public sealed partial class MyPage : Page
public MyPage()
InitializeComponent();
ListView.ItemsSource = new List<MyListItem>()
new MyListItem("Title1", "SubTitle1"),
new MyListItem("Title2", "SubTitle2")
还有 MyListItem 类:
class MyListItem
public string MyProperty get; set;
public string MyOtherProperty get; set;
public MyListItem(string myProperty, string myOtherProperty)
MyProperty = myProperty;
MyOtherProperty = myOtherProperty;
有问题的最小项目:
Project
【问题讨论】:
你的代码对我来说很好。 请提供MyListItem类代码 @VMaleev 编辑了我的问题 【参考方案1】:在处理自定义ControlTemplate
s 时需要使用TemplateBinding
表达式。这会将属性值绑定到与控件实例关联的任何相应属性。
<TextBlock Name="myColoredText"
Foreground="Green"
Text="TemplateBinding MyProperty" />
这将直接绑定到控件中的指定实例属性。由于WPF/WinRT控件为DependencyObjects
,所以常用DependencyProperties
:
public static readonly DependencyProperty MyPropertyProperty =
DependencyProperty.Register(
"MyProperty",
typeof(Boolean),
typeof(ListViewItem),
null
);
public bool MyProperty
get return (bool)GetValue(MyPropertyProperty);
set SetValue(MyPropertyProperty, value);
然后在声明一个新实例时,将按照 XAML 中的标准填充此属性:
<someNamespace:ListViewItem MyProperty=Binding ViewModelProperty />
您可以在 MSDN 上阅读有关 TemplateBinding 标记表达式的更多信息。
【讨论】:
那我应该把DependencyProperty
放在哪里呢?我不能把它放在我的自定义类中,因为它没有继承任何东西,它只存储了一些属性。此类仅用于创建要在我的ListView
中使用的数据列表
这是一个糟糕的解决方案,因为他必须注册他的模板的每个属性
但这就是自定义控件模板的工作方式!实际上听起来您想改用DataTemplate
。 msdn.microsoft.com/en-us/library/…
@JamesWright 我可以将VisualStateManager.VisualStateGroups
代码放在DataTemplate
中吗?我似乎无法让它工作。我需要它根据ListItem
当前所处的状态来更改我的布局。
用VisualStateManger.GoToElementState
替换您对VisualStateManger.GoToState
的调用可能会做到这一点,因为您可以定位位于另一个元素中的视觉状态。让我知道这对您有什么作用:msdn.microsoft.com/en-us/library/…【参考方案2】:
ControlTemplate
通常用于定义控件的外观。因此,将 XAML 放入 DataTemplate
并将其分配给 ListView.ItemTemplate
属性会容易得多。您可以从DataTemplate
访问所有自定义属性:
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Name="myColoredText" Foreground="Green"
Text="Binding MyProperty" /><!-- This will now work -->
</DataTemplate>
</ListView.ItemTemplate>
更新>>>
您还可以像这样使用ItemContainerStyle
属性中的DataTemplate
:
<Style x:Key="SomeStyle" TargetType="x:Type ListBoxItem">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate DataType="x:Type Your:DataType">
<TextBlock Name="myColoredText" Foreground="Green"
Text="Binding MyProperty" /><!-- This will now work -->
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
【讨论】:
是的,我已经尝试过了,但是我无法从我的ControlTemplate
设置前景色。当一个项目被选中时,我使用这个模板来改变外观。
然后将该代码移至DataTemplate
。或者,这可能会更好,尝试使用ItemContainerStyle
property。这通常用于您想要的...样式化数据项的容器。
我目前正在使用ItemContainerStyle
属性来设置这个ListViewItem
的样式。问题是我不能同时使用Binding MyProperty
(仅适用于DataTemplate
)和ItemContainerStyle
在选择或取消选择ListViewItem
时对其进行样式设置...我要么有默认样式,要么没有绑定。跨度>
【参考方案3】:
Wpf 仅支持绑定到属性,不支持绑定到字段。所以,你的 MyItemClass 应该是:
public class MyListItem
public string MyProperty get; set;
public string MyOtherProperty get; set;
public MyListItem(string myProperty, string myOtherProperty)
MyProperty = myProperty;
MyOtherProperty = myOtherProperty;
希望对你有帮助
【讨论】:
很遗憾这是我的错字,所以没有解决方案。 此代码至少适用于两个人。它看起来像测试项目,因此您可以共享问题可重现的整个项目 @vrwim MyListItem 是公开的吗? 我正在尝试制作一个测试项目,但它会立即崩溃......当我能够创建所述项目时,我会回复您。 将项目添加到我的问题中。【参考方案4】:在TextBox
中,使用:
Text="Binding Content.MyProperty,
RelativeSource=RelativeSource TemplatedParent"
【讨论】:
我收到AncestorType
在RelativeSource
上找不到的错误。我正在创建一个通用 Windows 应用程序。
对不起,错过了那个标签...我会编辑答案以获得更好的方法。
RelativeSource
使绑定的"DataContext"
成为控件本身,即 ListViewItem。所以现在ListViewItem.Content
属性可用,并将包含您设置为项目内容的对象,因此MyProperty
可用。
嘿@XAMeLi,非常感谢你的朋友!我搜索并工作了过去 3 天,无论我在网上得到什么关于我的问题的信息,每个人都用他自己的哲学解释了它,但是你在样式中的这一单行绑定对我有用......我不能给出你超过+1,否则我会给你100+。再次感谢。上帝祝福你! :)
@ZiaUrRahman 很高兴它有帮助。只有一点 - 这在Style
中不起作用,但仅在ControlTemplate
中起作用(也许DataTemplate
,但需要检查)。以上是关于如何在此 ControlTemplate 中进行绑定?的主要内容,如果未能解决你的问题,请参考以下文章
[UWP]如何使用代码创建DataTemplate(或者ControlTemplate)
百度程序员删库被判9个月,手机号一键解绑功能发布,推特再向马斯克妥协,今日更多大新闻在此...
是否可以在ControlTemplate中包含Xaml资源?
如何从代码隐藏中访问UserControl中样式的Setter中ControlTemplate中定义的Control实例?