我正在开发一个WPF应用程序,这是我的第一个,所以我正在学习。 基本情况很好,但我遇到了我现在正在尝试做的问题。似乎有很多方法可行,但我很确定我会走上使它变得更难的道路。
我需要的是关于实现一个UI的最简单方法的一些指导。
我正在使用c#4,wpf和MVVM模式。
我想要显示的数据如下所示:
obj1 ----< obj2 ----< OBJ 3 即单个obj1有许多obj2,它有许多(特别是1-3)obj3的
在我的屏幕上,我希望看到obj2元素的list / datagrid类型视图,其中嵌套了相关的obj3元素。
obj2元素需要显示一些文本值和一个复选框(在切换时将触发视图模型中的相应命令)。 obj3元素需要显示一个图像,可能是一些文本并且是可点击的(再次,向视图模型发出适当的命令)。
首先,我研究了为obj3元素创建自定义控件,基于ItemsControl的自定义控件,用于obj3元素列表,另一个自定义控件用于obj2元素,最后是另一个自定义控件,用于显示obj2元素列表。
然而,从某种程度上说,我感觉我已经大大过度复杂了。 我可以只使用用户控件吗?我甚至根本不需要它们,或者我可以只使用带有模板的常规List控件吗?
一些指示会非常受欢迎。 感谢。
答案 0 :(得分:0)
我花了很长时间才开始工作,因为我想要分享......
答案结果是一个嵌套列表控件,其中包含每个列表中项目的数据模板和相关视图模型。列表控件在WPF中比Winforms更灵活,你可以用它做任何事情。
我发现许多不同的东西在许多不同的网站上有所帮助,但核心细节来自Dr.WPF:http://drwpf.com/blog/category/collections/
我不会发布所有代码,因为它相当长。它的核心是首先在用户控件中设置列表视图:
<ListView Name="list" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
HorizontalContentAlignment="Stretch" Focusable="False"
IsSynchronizedWithCurrentItem="True" ItemsPanel="{StaticResource VerticalItemsPanel}"
ItemContainerStyle="{StaticResource Obj2ContainerStyle}" ItemsSource="{Binding Obj2List}">
</ListView>
这里的键是ItemsPanel和ItemContainerStyle。它们定义了包含所有列表项的面板的属性以及每个列表项的样式。 它们包含在用户控件的资源中。
<ItemsPanelTemplate x:Key="VerticalItemsPanel">
<StackPanel Orientation="Vertical" Focusable="False" HorizontalAlignment="Stretch" />
</ItemsPanelTemplate>
<Style x:Key="Obj2ContainerStyle" TargetType="{x:Type ListViewItem}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Enabled}" Value="False">
<Setter Property="Background" Value="LightSalmon"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding Path=Enabled}" Value="True">
<Setter Property="Background" Value="PaleGreen"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
我也有数据模板。第一个告诉系统使用第二个来显示Obj2ViewModel类型的对象
<DataTemplate DataType="{x:Type src:Obj2ViewModel}">
<ContentControl x:Name="Obj2Host" Focusable="False" Content="{Binding}"
ContentTemplate="{StaticResource Obj2ViewTemplate}" />
</DataTemplate>
<DataTemplate x:Key="Obj2ViewTemplate">
<DataTemplate.Resources>
<ItemsPanelTemplate x:Key="HorizontalItemsPanel">
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
<Style x:Key="Obj3ContainerStyle" TargetType="{x:Type ListViewItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Grid>
<Rectangle StrokeThickness="1" Stroke="#FF000000" Margin="0" />
<ContentPresenter x:Name="ContentHost" Margin="{TemplateBinding Padding}"
HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="LabelStyle" TargetType="{x:Type Label}">
<Setter Property="Padding" Value="0,0,4,0" />
<Setter Property="HorizontalAlignment" Value="Left" />
</Style>
<Style x:Key="DataStyle" TargetType="{x:Type TextBlock}">
<Setter Property="Padding" Value="0,0,4,0" />
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="FontWeight" Value="Bold" />
</Style>
</DataTemplate.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Content="{StaticResource Label1Text}" Style="{StaticResource LabelStyle}"/>
<Label Grid.Row="1" Grid.Column="0" Content="{StaticResource Label2Text}" Style="{StaticResource LabelStyle}"/>
<Label Grid.Row="2" Grid.Column="0" Content="{StaticResource Label3Text}" Style="{StaticResource LabelStyle}"/>
<Label Grid.Row="3" Grid.Column="0" Content="{StaticResource Label4Text}" Style="{StaticResource LabelStyle}"/>
<TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding Property1}" Style="{StaticResource DataStyle}"/>
<TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding Property2}" Style="{StaticResource DataStyle}"/>
<TextBlock Grid.Row="2" Grid.Column="1" Text="{Binding Property3}" Style="{StaticResource DataStyle}"/>
<TextBlock Grid.Row="3" Grid.Column="1" Grid.ColumnSpan="2" Text="{Binding Property4}" Style="{StaticResource DataStyle}"/>
<ListView Grid.Row="0" Grid.RowSpan="3" Grid.Column="2" Name="Obj3List"
HorizontalAlignment="Right" VerticalAlignment="Center"
IsSynchronizedWithCurrentItem="True"
ItemsPanel="{StaticResource HorizontalItemsPanel}"
ItemsSource="{Binding Obj3s}"
ItemContainerStyle="{StaticResource Obj3ContainerStyle}"
BorderThickness="0"
Background="Transparent">
</ListView>
<CheckBox Grid.Row="0" Grid.RowSpan="4" Grid.Column="3" VerticalAlignment="Center"
IsChecked="{Binding Property5}" IsEnabled="{Binding NotExpired}" >
</CheckBox>
<Image Grid.Row="0" Grid.RowSpan="4" Grid.Column="4" Source="{StaticResource DeleteIcon}" Stretch="None">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseUp">
<cmd:EventToCommand PassEventArgsToCommand="False" Command="{Binding DeleteObj2Command, Mode=OneWay}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Image>
</Grid>
</DataTemplate>
上面的第二个数据模板包含另一个列表视图。这一个包含Obj3项目。 这些样式在DataTemplate的资源部分中指定。 最后,User控件的资源还包含Obj3元素的数据模板:
<DataTemplate DataType="{x:Type src:Obj3ViewModel}">
<ContentControl x:Name="Obj3Host" Focusable="False" Content="{Binding}"
ContentTemplate="{StaticResource Obj3ViewTemplate}" />
</DataTemplate>
<DataTemplate x:Key="Obj3ViewTemplate">
<Image Source="{Binding Image}" Stretch="None">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseUp">
<cmd:EventToCommand PassEventArgsToCommand="False" Command="{Binding ToggleEnabledCommand, Mode=OneWay}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Image>
</DataTemplate>
请注意,EventToCommand的功能归功于MVVM Light工具包。它不是标准的.NET。