我正在学习WPF,我认为我错过了一些用户控件。我将尝试通过示例进行演示。基本上,假设我有一个树视图,我想将标签文本绑定到树视图selectedItem。这看起来很简单:
<!-- Window.xaml -->
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="100" />
</Grid.RowDefinitions>
<TreeView Name="MyTreeView">
<TreeViewItem Header="Root">
<TreeViewItem Header="Item1"></TreeViewItem>
<TreeViewItem Header="Item2"></TreeViewItem>
</TreeViewItem>
</TreeView>
<Label Content="{Binding ElementName=MyTreeView, Path=SelectedItem.Header}" Grid.Row="1"></Label>
</Grid>
现在,为了使事情变得复杂,我将添加一个用户控件。用户控件基本上是网格中的TreeView:
<!-- ExampleUserControl.xaml -->
<UserControl>
<Grid>
<TreeView Name="UserControlTreeView">
<TreeViewItem Header="Root">
<TreeViewItem Header="Item1"></TreeViewItem>
<TreeViewItem Header="Item2"></TreeViewItem>
</TreeViewItem>
</TreeView>
</Grid>
</UserControl>
目的是用usercontrol替换上面使用的vanilla树视图,并根据所选内容更改标签内容。所以,我尝试这样的事情:
<Window>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="100" />
</Grid.RowDefinitions>
<local:ExampleUserControl1 x:Name="MyUserControl">
</local:ExampleUserControl1>
<Label Content="{Binding ElementName=MyUserControl, Path=SelectedItem.Header}" Grid.Row="1"></Label>
</Grid>
</Window>
这会编译并运行,但是当我在树视图中选择项目时,标签不会更改。我想我理解为什么:用户控件包含树视图,但显然不是树视图。我不确定解决这个问题的最佳方法。我可以想到一种似乎有问题的方法:
这适用于一个属性或少数属性,但是对树视图中的每个属性执行此操作的想法似乎是严重浪费代码+时间。有没有办法仍然使用用户控件,但使其行为像普通的TreeView?
答案 0 :(得分:2)
无法从外部访问子控件。一种方法是在SelectedItem
后面的代码中包含封装属性,并绑定到您已经提到的外部的属性。
但我建议使用UserControl的Tag
属性来包含TreeView
的引用并从外部绑定到Tag
属性。这样您就不必在后面的代码中创建多个属性。
使用x:Reference绑定到TreeView:
<UserControl Tag="{Binding Source={x:Reference UserControlTreeView}}">
<Grid>
<TreeView Name="UserControlTreeView">
<TreeViewItem Header="Root">
<TreeViewItem Header="Item1"></TreeViewItem>
<TreeViewItem Header="Item2"></TreeViewItem>
</TreeViewItem>
</TreeView>
</Grid>
</UserControl>
现在绑定标签控件:
<Label Content="{Binding ElementName=MyUserControl,
Path=Tag.SelectedItem.Header}"/>
答案 1 :(得分:1)
你的理由是正确的,因为它不起作用。 LabelI看不到SelectedItem属性。
您可以像往常一样使用TreeView,而不是使用UserControl来简单地托管TreeView,而是绑定到它的ItemsSource。例如:
<!--MainWindow.xaml-->
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:coll="clr-namespace:System.Collections;assembly=mscorlib"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.Resources>
<coll:ArrayList x:Key="data">
<TreeViewItem Header="Parent 1">
<TreeViewItem Header="Child 1"/>
<TreeViewItem Header="Child 2"/>
</TreeViewItem>
<TreeViewItem Header="Parent 2">
<TreeViewItem Header="Child 1"/>
<TreeViewItem Header="Child 2"/>
</TreeViewItem>
</coll:ArrayList>
</Grid.Resources>
<TreeView Grid.Row="0" ItemsSource="{StaticResource data}" x:Name="tv1"/>
<Label Grid.Row="1" Content="{Binding ElementName=tv1, Path=SelectedItem.Header}"/>
</Grid>
</Window>
对于这个例子,我使用的是StaticResource,它不是动态的...... BUT ,你所要做的就是绑定到itemsource。这是IMHO处理多个TreeView的最佳方式。
修改强>
再看一遍,我发现你更倾向于让usercontrol像树视图一样,而不仅仅是得到结果。
你无法完全按照UserControl进行操作。
你想要做的是创建一个扩展treeview的新类。它不需要是用户控件。
答案 2 :(得分:1)
尝试以下方式。
在用户控件中创建TreeView类型的公共属性,并返回树视图,如下所示。
//ExampleUserControl.xaml.cs
public TreeView UTreeView
{
get
{
return UserControlTreeView;
}
}
然后在Window.xaml中使用此属性,如下所示。
<local:ExampleUserControl1 x:Name="MyUserControl">
</local:ExampleUserControl1>
<Label Content="{Binding ElementName=MyUserControl, Path=UTreeView.SelectedItem.Header}" Grid.Row="1"></Label>