我是一个.net新手,我一直致力于我的第一个大银光项目。因此,请原谅语言的缺失和问题的长度。但我的问题如下。
该项目是根据MVVM模式构建的(在本例中我使用的是LightMVVM)。大多数视图都包含ListBoxes。这些列表框需要处理多种不同类型的数据,每种数据都有自己的视觉外观。经过一些探讨,我解码了tp尝试这个实现datatemplate选择:
http://silverscratch.blogspot.com/2010/04/changing-data-templates-at-run-time.html
但是,我的一些项目具有需要与视图模型通信的子控件。从我一直在阅读带有元素绑定的命令是处理这个问题的最佳方法。
所以,例如:
<Grid x:Name="NavMainLayoutRoot" DataContext="{Binding Source={StaticResource NavMainViewModelDataSource}}" Margin="15,0,0,0">
....
<ListBox x:Name="MenuListBox" HorizontalAlignment="Left" Background="{x:Null}" BorderBrush="{x:Null}" Foreground="White" ItemsSource="{Binding Items}" ItemContainerStyle="{StaticResource MainNavigationButtonStyle}" Padding="0" VerticalAlignment="Top" >
<ListBox.RenderTransform>
<CompositeTransform/>
</ListBox.RenderTransform>
<ListBox.ItemTemplate>
<DataTemplate>
<xxxControls:SelectableContentControl TemplateName="{Binding Path=Type}" Content="{Binding Details}" IsTabStop="{Binding IsHitTestEnabled}">
<xxxControls:SelectableContentControl.Templates>
<DataTemplate>
<local:GenericItem />
</DataTemplate>
<DataTemplate x:Name="navbutton">
<local:MainNavItem />
</DataTemplate>
</xxxControls:SelectableContentControl.Templates>
</xxxControls:SelectableContentControl>
</DataTemplate>
</ListBox.ItemTemplate>
....
MainNavItem,简化为:
<Grid x:Name="NavItemRoot" VerticalAlignment="Top" Margin="0,0,0,0">
<Button Content="{Binding Label}" VerticalAlignment="Top" Style="{StaticResource MainNavItemButtonStyle}" HorizontalAlignment="Left" Margin="5,0" Command="{Binding DataContext.NavButtonClick, ElementName=NavMainLayoutRoot}"/>
</Grid>
问题是这不起作用。因此,对于笑脸,我继续将MainNavItem的代码直接复制并粘贴到标签中,就像魔术一样,它开始工作。
由于我在整个应用程序中重复使用了很多这些项目模板,因此将它们放在包含好的外部文件中非常好而不是我想要放弃的东西。
((考虑一下,这个例子不是最好的,足以说这些数据模板中的一些包含多个控件,我不能只在列表框上使用selectedItem来处理选定的事件。)) p>
所以欢迎任何建议。这里最好的做法是什么?
答案 0 :(得分:0)
我的第一个想法是,MainNavItem用户控件中的某些内容正在将其DataContext设置为其他内容。如果您没有设置DataContext,它应该自动从MenuListBox中的当前项中选取它。
您可以尝试创建一个测试值转换器并在其中放置一个断点来检查数据上下文在运行时的状态。
public class TestConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
Debug.WriteLine("TestConverter.Convert(value := {0}, targetType := {1}, parameter := {2}, culture := {3})",
value, targetType, parameter, culture);
return value; // put break point here to test data binding
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
Debug.WriteLine("TestConverter.ConvertBack(value := {0}, targetType := {1}, parameter := {2}, culture := {3})",
value, targetType, parameter, culture);
return value;
}
}
将MainNavItem修改为如下所示,以便在运行时中断TestConverter。
<UserControl.Resources>
<ResourceDictionary>
<TestConverter x:Key="TestConverter" />
</ResourceDictionary>
</UserControl.Resources>
<Grid x:Name="NavItemRoot" DataContext="{Binding Converter={StaticResource TestConverter}}">
<Button Content="{Binding Path=Label, Converter={StaticResource TestConverter}}" />
</Grid>
这将帮助您确定数据绑定的问题。
我怀疑你的命令存在的问题是你正在使用元素到元素的数据绑定来尝试绑定到你当前所在的用户控件之外的元素。这不行。相反,尝试在App.xaml中设置NavMainViewModelDataSource静态资源,然后可以从用户控件直接绑定到它。
<Button Content="{Binding Label}" Command="{Binding Path=NavButtonClick, Source={StaticResource NavMainViewModelDataSource}}" />