C# 指定要在运行时显示的多个WPF数据网格之一
在我的应用程序中,我希望有一个下拉框来选择要编辑的表(大约20个)。每个表都应该由自己的WPF数据网格表示。(我曾考虑过使用一个DataGrid,并在运行时创建一组新列,其中包含代码隐藏,但这似乎不太像XAML。) 我的下拉列表位于UserControl中(因为它是大型应用程序的一部分)。我相信(根据我的研究),20个数据网格中的一个数据网格的占位符应该是一个ContentControl,在这里用作占位符:C# 指定要在运行时显示的多个WPF数据网格之一,c#,wpf,xaml,binding,user-controls,C#,Wpf,Xaml,Binding,User Controls,在我的应用程序中,我希望有一个下拉框来选择要编辑的表(大约20个)。每个表都应该由自己的WPF数据网格表示。(我曾考虑过使用一个DataGrid,并在运行时创建一组新列,其中包含代码隐藏,但这似乎不太像XAML。) 我的下拉列表位于UserControl中(因为它是大型应用程序的一部分)。我相信(根据我的研究),20个数据网格中的一个数据网格的占位符应该是一个ContentControl,在这里用作占位符: <UserControl x:Class="MyClass" ...
<UserControl x:Class="MyClass" ...
xmlns:my="clr-namespace:MyNamespace"
DataContext="{Binding ViewModel}">
<StackPanel>
<Grid>
<ComboBox Name="DataPaneComboBox" HorizontalAlignment="Stretch"
IsReadOnly="True" MinWidth="120"
Focusable="False" SelectedIndex="0"
DockPanel.Dock="Left" Grid.Column="0"
SelectionChanged="DataPaneComboBox_SelectionChanged">
<ComboBoxItem Name="FirstOption" Content="Choice 1" />
<ComboBoxItem Name="SecondOption" Content="Choice 2" />
<ComboBoxItem Name="ThirdOption" Content="Choice 3" />
</ComboBox>
</Grid>
<ContentControl Name="DataGridView" Margin="0,3,0,3" Content="{Binding CurrentView}" />
</StackPanel>
ViewModel(ObservableObject类实现INotifyPropertyChanged接口):
以及运行时可以在中替换的20个左右用户控件之一:
<UserControl x:Class="Choice1Control"
xmlns:my="clr-namespace:MyNamespace">
<DataGrid ItemsSource="{Binding Choice1Objects}" />
<!-- ... -->
</DataGrid>
</UserControl>
当用户更改下拉列表时,我希望程序加载相应的DataGrid。现在我看不到子用户控件(这里,Choice1Control
)。我直接添加了这个孩子(没有中间的ContentControl),效果很好
我尝试了DataContext和UserControl内容绑定的几乎所有组合。我是WPF的新手,所以我可能错过了一些显而易见的东西。谢谢 路径需要一个源(Source、DataContext、RelativeSource、ElementName)。ElementName只能用于引用在XAML中通过x:Name声明的元素 路径需要一个源(Source、DataContext、RelativeSource、ElementName)。ElementName只能用于引用在XAML中通过x:Name声明的元素 由于某种原因,我从未想到在运行时会有绑定错误清楚地写入日志中。我四处摸索,直到我真正得到了一条有用的信息,能够找到问题的根源 似乎在ContentControl继承根UserControl的DataContext之前,它就被拦截了。(或者,我对DataContext是如何继承/传播的印象是错误的。) 最后,我更改了
MyClass
构造函数,将DataContext显式指定为ViewModel
public MyClass() {
InitializeComponent();
ViewModel = new MyViewModel();
ViewModel.CurrentView = new DataGridChoice1();
this.DataContext = ViewModel; // <-- Added this line
}
publicmyclass(){
初始化组件();
ViewModel=新的MyViewModel();
ViewModel.CurrentView=新的DataGridChoice1();
this.DataContext=ViewModel;//出于某种原因,我从未想到在运行时会在日志中清楚地写下绑定错误。我仔细研究了一下,直到我真正得到了一条有用的消息,并找到了问题的根源
根用户控件的DataContext似乎在被ContentControl继承之前就被截获了。(或者,我对DataContext是如何继承/传播的印象是错误的。)
最后,我更改了MyClass
构造函数,将DataContext显式指定为ViewModel
public MyClass() {
InitializeComponent();
ViewModel = new MyViewModel();
ViewModel.CurrentView = new DataGridChoice1();
this.DataContext = ViewModel; // <-- Added this line
}
publicmyclass(){
初始化组件();
ViewModel=新的MyViewModel();
ViewModel.CurrentView=新的DataGridChoice1();
this.DataContext=ViewModel;//您在代码背后的哪里分配数据源,即ViewSource..等等?您的意思是什么?我的印象是,将DataContext设置为classViewModel
,并将ContentControl的内容设置为指向CurrentView
,就足以表明在指定控件之前。你能说得更具体些吗?我在绑定方面说得更多。我看到你在使用{Binding},但是绑定需要某种源代码,那么Content=“{Binding CurrentView}”
应该是什么呢?我没有绑定到XAML中的资源或任何东西。(为了好玩,我尝试了Content=”{Binding RelativeSource={RelativeSource Self},Path=CurrentView}“
这似乎没有效果。)如果我发布的内容对您没有意义,我将编辑/删除它,并改进我的示例,以帮助您朝更好的方向前进…谢谢您在代码中为ViewSource等分配数据源?您的意思是什么?我的印象是,将DataContext设置为classViewModel
和setti将ContentControl的内容指向CurrentView
足以指示控件的指定位置。您能更具体一点吗?我在绑定方面讲得更多..我看到您使用的是{Binding},但是绑定需要某种源代码,那么Content=“{Binding CurrentView}”应该是什么呢
be?我没有绑定到XAML中的资源或任何东西。(为了好玩,我尝试了Content=“{binding RelativeSource={RelativeSource Self},Path=CurrentView}”
,但似乎没有效果。)如果我所发布的内容对您没有意义,我将编辑/删除它,并改进我的示例,以帮助您朝更好的方向前进…感谢您没有指定绑定关系资源有效地覆盖DataContext?我所做的有什么错:将DataContext指定为附加的ViewModel?我对您示例的印象是t它将使用父窗口的DataContext,这是我的应用程序的顶层,它的DataContext与此处使用的DataContext不同。为了好玩,我还尝试了{Binding RelativeSource={RelativeSource Mode=FindAncestor,antestorType={x:Type UserControl},Path=CurrentView}
,但结果相同:-(如果您尝试这样做,这不是问题。作为测试,我将我的
替换为
,选择1控件的显示与预期一致。DataGrid本身的DataContext和绑定是正常的;将子DataGrid附加到父UserControl的DataContext/绑定是不正常的。(谢谢您的持续帮助,顺便说一句。)啊哈..现在我明白了..我还以为是另一种情况..现在已经很晚了..我已经在这个问答环节上呆了一整天..我很抱歉..你可能还需要考虑为
public MyClass() {
InitializeComponent();
ViewModel = new MyViewModel();
ViewModel.CurrentView = new DataGridChoice1();
this.DataContext = ViewModel; // <-- Added this line
}