我为我的应用程序编写了一个简单的UpDown UserControl。我在ListBox中渲染它,以便在添加UpDown控件时,它们会水平堆叠。
我的UserControl有一个DependencyProperty,对应于UpDown控件内部的数字,称为NumberProperty。
我通过数据绑定向ListBox添加了多个UpDown控件,其中ListBox的ItemsSource只是一个名为ObservableCollection<NumberGroup>
的{{1}}。每个NumberGroups
只有一个名为Number的成员,我希望在呈现ListBox时该数字出现在其各自的UpDown控件中。
我的ListBox在XAML中定义如下:
NumberGroup
和ListBox的DataTemplate是:
<ListBox Grid.Row="1" ItemsSource="{Binding NumberGroups}" ItemTemplate="{StaticResource NumberGroupTemplate}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" Width="Auto" Height="Auto" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
这有点令人困惑,因为我在UpDown UserControl中将DependencyProperty <DataTemplate x:Key="RackTemplate">
<StackPanel Orientation="Vertical">
<TextBlock>Group</TextBlock>
<updown:UpDown Number="{Binding Number}" />
</StackPanel>
</DataTemplate>
命名为与NumberGroup类中的属性相同。 NumberGroup仅仅是:
Number
当我运行应用程序时,我已经知道它不会起作用,因为“输出”窗口告诉我:
public class NumberGroup
{
public int Number { get; set; }
}
好的,所以它绑定到UserControl而不是ListItem ......无法写入。因此,作为测试,我从Resources和ListBox定义中删除了DataTemplate并重新运行它。在ListBox中,我得到了一堆System.Windows.Data Error: 39 : BindingExpression path error: 'Number' property not found on 'object' ''UpDown' (Name='')'. BindingExpression:Path=Number; DataItem='UpDown' (Name=''); target element is 'UpDown' (Name=''); target property is 'Number' (type 'Int32')
s,这正是我所期待的!
那么当我这样做时,它似乎与ListItem绑定,但是当我定义ItemTemplate时它想要绑定到UpDown控件?任何解释都会非常感激。我已经阅读了WPF博士的文章,并且不明白为什么会发生这种情况。
更新
好的,我想出了与我的问题有关的事情。在UserControl中,我将DataContext设置为自身,以便我可以处理处理Up和Down按钮的NumberGroup
。但由于某些原因我还不明白,它与ListItem的数据绑定混淆了!如果UserControl包含在ListItem中,为什么会发生这种情况?
答案 0 :(得分:1)
当您将UserControl的DataContext内部设置为自身时,您获得的效果与执行此操作完全相同:
<updown:UpDown DataContext="{Binding RelativeSource={RelativeSource Self}}" />
显然现在你设置的没有明确Source定义的任何Bindings都会使用UpDown控件作为它们的上下文。因此,当您尝试绑定到Number属性时,它正在UpDown上寻找Number属性而不是ListBoxItem的数据。这正是您的错误告诉您的。
要避免这种情况,请将UserControl中的DataContext设置更改为应用于控件内的元素,例如带有x:Name的根布局Grid。
<Grid x:Name="LayoutRoot">
...
</Grid>
并在代码或XAML中设置DataContext。
LayoutRoot.DataContext = this;