我有一个GridView,它有几个按钮。其中一个由以下模板定义:
<DataTemplate x:Name="SubjectItemTemplate">
<Canvas Width="340" Height="170" VerticalAlignment="Top">
<Controls:ThreeImageButton HorizontalAlignment="Center" VerticalAlignment="Top" Margin="0,0,0,0"
NormalStateImageSource="{Binding NormalImage}"
HoverStateImageSource="{Binding HoverImage}"
PressedStateImageSource="{Binding PressedImage}" Command="{Binding Path=NavigateToUnitsPage}"
CommandParameter="{Binding}" Canvas.Left="0" Canvas.Top="0">
</Controls:ThreeImageButton>
</Canvas>
</DataTemplate>
现在我有一个自定义控件,你可以看到,叫做ThreeImageButton。当我自己使用它时按钮工作正常。但是当我在DataTemplate中使用它时,它不会将属性绑定到后面的代码。
现在,我有
x:Name="MyThreeImageButton"
自定义按钮定义中的。我像这样连接到代码隐藏:
<TextBlock Text="{Binding ElementName=MyThreeImageButton, Path=NormalStateImageSource}"/>
(这只是一个显示文本的测试,在实际代码中我将图像源分配给元素引用的另一个属性)。
现在,TextBlock中没有显示任何内容。我应该用什么来达到我的属性的正确绑定语法是什么?
谢谢!
编辑:我在InitializeComponent函数中设置变量,我在DependencyProperty上使用SetValue。
编辑:让我添加以下信息以便更清楚
情景I: 在DataTemplate for GridView中:
<UserControl CustomParameter="Literal Text">
在UserControl中:
<TextBlock Text="{Binding CustomParameter}">
在UserControl .cs中的:this.DataContext = this 作品!
情景二: 在DataTemplate for GridView中:
<UserControl CustomParameter="{Binding ValueFromDataItem">
在UserControl中:
<TextBlock Text="{Binding CustomParameter}">
在UserControl .cs中的:this.DataContext = this 都能跟得上!
答案 0 :(得分:0)
我明白了,
因此,在用户控件中设置与自定义属性的双向绑定可能会非常棘手,因为用户控件无法绑定到CLR属性。不仅如此,在用户控件上设置数据上下文对其内部的绑定具有意外的影响。
您可以使用一点点代码来解决这些问题。基本上使用依赖项属性支持CLR属性,并在子元素而不是root用户控件上设置数据上下文。
看一下这个样本。让我们假装你有以下MainPage。 MainPage最终将使用我们的自定义用户控件。所以让我们开始吧。
以下是代码隐藏:
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
this.DataContext = new /* your view model */
{
Title = Guid.NewGuid().ToString(),
};
}
}
在上面的代码中,我使用简单的匿名类来模拟复杂的视图模型。像你这样实现你自己是愚蠢的,但与此同时,用完整的脚手架构建一个简单的样本对我来说是愚蠢的。我提出这个问题只是因为它不会让你感到困惑 - 因为它可能看起来像是在推荐这种方法。
以下是XAML:
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<local:MyUserControl Text="{Binding Title}" />
</Grid>
在上面的XAML中,绝对没什么特别的。我已经在本地命名空间中引用了用户控件,我只是在这里声明它。
好了,现在我们有了控件的使用者,值得指出的是,在测试中,开发人员可能会错误地认为他们的绑定工作正常,因为他们使用字面值进行测试。文字值绑定很好。它是从底层视图模型中绑定的。
让我们说另一件事,一些开发人员倾向于避免依赖属性,因为需要更多的打字。人们记得[kbd] propdp [/ kbd]是一个方便的Visual Studio片段,它为你存储一个依赖属性。
看看这个用户控件。它有两个控件,一个TextBox和一个TextBlock,用于演示此绑定方法的OneWay和TwoWay功能。我们还在用户控件上实现了INotifyPropertyChanged。在大多数情况下,在用户控件的情况下添加视图模型是过度的,因为用户控件已经像视图模型一样工作。这取决于开发人员,但对我来说似乎很蠢。
以下是代码:
public sealed partial class MyUserControl : UserControl, INotifyPropertyChanged
{
public MyUserControl()
{
this.InitializeComponent();
}
// text property
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValueDp(TextProperty, value); }
}
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(string), typeof(MyUserControl), null);
// bindable
public event PropertyChangedEventHandler PropertyChanged;
void SetValueDp(DependencyProperty property, object value,
[System.Runtime.CompilerServices.CallerMemberName] String propertyName = null)
{
SetValue(property, value);
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
在上面的ode中,我创建了一个“Text”属性并使用依赖项属性对其进行了备份。为了重用,我还实现了SetValueDp(),如果我有多个属性,可以一次又一次地使用它。即使这个演示只有一个,我想要包括这个,因为重复逻辑肯定会被抽象出来。
以下是XAML:
<Grid Background="Black" DataContext="{Binding ElementName=userControl}">
<StackPanel>
<TextBox Text="{Binding Text, Mode=TwoWay}"
MinHeight="100" Padding="15" FontWeight="Light" FontSize="50" />
<TextBlock Text="{Binding Text}"
MinHeight="100" Padding="15" FontWeight="Light" FontSize="50" />
</StackPanel>
</Grid>
在上面的XAML中,我没有任何特殊的约束力。语法只使用适合控件的模式绑定到Text属性。就像你会做的一样。但是,值得注意的是DataContext未在用户控件上设置。相反,它是在网格上设置的。事实上,除了用户控件之外的树中的任何控件都可以像这样使用。只是不要设置用户控件的数据上下文。
就是这样。
我测试了它以确保它有效。演示单向和双向绑定在这里非常方便。我甚至可能将其变成一个博客,以防其他开发人员想要找到它并且没有发现这个问题。谢谢你的提问!
祝你好运!
答案 1 :(得分:-1)
正如评论所提到的,您的DataTemplate将项目的datacontext放置到您要添加到列表中的任何对象。这与周围用户控件的数据上下文不同。如果要引用该datacontext的命令,请在DataTemplate的绑定中执行以下操作:
{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.NormalImage}
这是说出去找到用户控件祖先并使用其datacontext然后查找NormalImage属性。如果遇到问题,请检查输出窗口是否存在绑定错误。它在查找绑定问题时非常有用。