WPF 优化 XAML 代码
Posted
技术标签:
【中文标题】WPF 优化 XAML 代码【英文标题】:WPF Optimize XAML code 【发布时间】:2014-04-02 19:35:43 【问题描述】:有没有更有效的方式来编写以下 XAML 代码? (当我说更高效时,我的意思是更少重复)。尤其是超链接和扩展器。谢谢!
<Window x:Class="InterfazOhmio.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Background>
<ImageBrush ImageSource="Imagenes/background.jpg"></ImageBrush>
</Window.Background>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200"></ColumnDefinition>
</Grid.ColumnDefinitions>
<ListBox ScrollViewer.VerticalScrollBarVisibility="Auto">
<ListBox.Resources>
<Style TargetType="x:Type Expander">
<Setter Property="IsExpanded"
Value="Binding Path=IsSelected, RelativeSource=RelativeSource AncestorType=x:Type ListBoxItem"/>
</Style>
</ListBox.Resources>
<ListBox.Template>
<ControlTemplate TargetType="x:Type ListBox">
<ItemsPresenter/>
</ControlTemplate>
</ListBox.Template>
<ListBox.ItemContainerStyle>
<Style TargetType="x:Type ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="x:Type ListBoxItem">
<ContentPresenter Content="TemplateBinding Content"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
<Expander Margin="2" Background="OliveDrab">
<Expander.Header>
<BulletDecorator>
<BulletDecorator.Bullet>
<Image Source="Iconos/Pedidos.png" Width="64" Height="64" HorizontalAlignment="Left" VerticalAlignment="Top" />
</BulletDecorator.Bullet>
<TextBlock Margin="10,0,0,0" Text="Pedidos" VerticalAlignment="Center" HorizontalAlignment="Stretch" Foreground="White" />
</BulletDecorator>
</Expander.Header>
<WrapPanel>
<Label Margin="20,5,5,5" HorizontalAlignment="Stretch">
<Hyperlink TextDecorations="None">
<TextBlock Foreground="White" Text="Nuevo Pedido"/>
</Hyperlink>
</Label>
<Label Margin="20,5,5,5" HorizontalAlignment="Stretch">
<Hyperlink TextDecorations="None">
<TextBlock Foreground="White" Text="Consultar Pedidos" />
</Hyperlink>
</Label>
<Label Margin="20,5,5,5" HorizontalAlignment="Stretch">
<Hyperlink TextDecorations="None">
<TextBlock Foreground="White" Text="Pedidos Pendientes" />
</Hyperlink>
</Label>
</WrapPanel>
</Expander>
<Expander Margin="2" Background="OrangeRed">
<Expander.Header>
<BulletDecorator>
<BulletDecorator.Bullet>
<Image Source="Iconos/Remitos.png" Width="64" Height="64" HorizontalAlignment="Left" VerticalAlignment="Top" />
</BulletDecorator.Bullet>
<TextBlock Margin="10,0,0,0" Text="Remitos" VerticalAlignment="Center" HorizontalAlignment="Stretch" Foreground="White" />
</BulletDecorator>
</Expander.Header>
<WrapPanel>
<Label Margin="20,5,5,5" HorizontalAlignment="Stretch">
<Hyperlink TextDecorations="None">
<TextBlock Foreground="White" Text="Nuevo Remito"/>
</Hyperlink>
</Label>
<Label Margin="20,5,5,5" HorizontalAlignment="Stretch">
<Hyperlink TextDecorations="None">
<TextBlock Foreground="White" Text="Consultar Remitos" />
</Hyperlink>
</Label>
<Label Margin="20,5,5,5" HorizontalAlignment="Stretch">
<Hyperlink TextDecorations="None">
<TextBlock Foreground="White" Text="Remitos Pendientes" />
</Hyperlink>
</Label>
</WrapPanel>
</Expander>
<Expander Margin="2" Background="Teal">
<Expander.Header>
<BulletDecorator>
<BulletDecorator.Bullet>
<Image Source="Iconos/Facturas.png" Width="64" Height="64" HorizontalAlignment="Left" VerticalAlignment="Top" />
</BulletDecorator.Bullet>
<TextBlock Margin="10,0,0,0" Text="Facturas" VerticalAlignment="Center" HorizontalAlignment="Stretch" Foreground="White" />
</BulletDecorator>
</Expander.Header>
<StackPanel>
<Label Margin="20,5,5,5" HorizontalAlignment="Stretch">
<Hyperlink TextDecorations="None">
<TextBlock Foreground="White" Text="Nueva Factura"/>
</Hyperlink>
</Label>
<Label Margin="20,5,5,5" HorizontalAlignment="Stretch">
<Hyperlink TextDecorations="None">
<TextBlock Foreground="White" Text="Consultar Facturas" />
</Hyperlink>
</Label>
</StackPanel>
</Expander>
</ListBox>
</Grid>
</Window>
更新
好的,我尝试了建议的解决方案,它可以工作,但结果中存在一些小的视觉差异,如当时的图片所示:
左侧是原始菜单。右侧是带有 viewModel 的新视图:
选择项被标记,而不是在原始菜单中。 扩展器的宽度太短
这是 XAML 的结果:
<Window x:Class="InterfazOhmio.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:InterfazOhmio"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:MainViewModel/>
</Window.DataContext>
<Window.Background>
<ImageBrush ImageSource="Imagenes/background.jpg"></ImageBrush>
</Window.Background>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200"></ColumnDefinition>
</Grid.ColumnDefinitions>
<ListBox ItemsSource="Binding myMenu">
<ListBox.Resources>
<Style TargetType="x:Type Expander">
<Setter Property="IsExpanded"
Value="Binding Path=IsSelected, RelativeSource=RelativeSource AncestorType=x:Type ListBoxItem"/>
</Style>
</ListBox.Resources>
<ListBox.Template>
<ControlTemplate TargetType="x:Type ListBox">
<ItemsPresenter/>
</ControlTemplate>
</ListBox.Template>
<ListBox.ItemTemplate>
<DataTemplate>
<Expander Margin="2" Background="Binding Color">
<Expander.Header>
<BulletDecorator>
<BulletDecorator.Bullet>
<Image Source="Binding ImageSource" Width="64" Height="64" HorizontalAlignment="Left" VerticalAlignment="Top" />
</BulletDecorator.Bullet>
<TextBlock Margin="10,0,0,0" Text="Binding Title" VerticalAlignment="Center" HorizontalAlignment="Stretch" Foreground="White" />
</BulletDecorator>
</Expander.Header>
<ListBox ItemsSource="Binding Options" Background="Transparent">
<ListBox.ItemTemplate>
<DataTemplate>
<Label Margin="20,5,5,5" HorizontalAlignment="Stretch">
<Hyperlink TextDecorations="None">
<TextBlock Foreground="White" Text="Binding"/>
</Hyperlink>
</Label>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Expander>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Window>
有人可以帮我吗?谢谢! 更新二
差不多了!!!
XAML:
<Window x:Class="InterfazOhmio.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:InterfazOhmio"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:MainViewModel/>
</Window.DataContext>
<Window.Background>
<ImageBrush ImageSource="Imagenes/background.jpg"></ImageBrush>
</Window.Background>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200"></ColumnDefinition>
</Grid.ColumnDefinitions>
<ItemsControl ItemsSource="Binding myMenu">
<ItemsControl.Resources>
<Style TargetType="x:Type Expander">
<Setter Property="IsExpanded"
Value="Binding Path=IsSelected, RelativeSource=RelativeSource AncestorType=x:Type ListBoxItem"/>
</Style>
</ItemsControl.Resources>
<ItemsControl.Template>
<ControlTemplate TargetType="x:Type ItemsControl">
<ItemsPresenter/>
</ControlTemplate>
</ItemsControl.Template>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Expander Margin="2" Width="196" Background="Binding Color">
<Expander.Header>
<BulletDecorator>
<BulletDecorator.Bullet>
<Image Source="Binding ImageSource" Width="64" Height="64" HorizontalAlignment="Left" VerticalAlignment="Top" />
</BulletDecorator.Bullet>
<TextBlock Margin="10,0,0,0" Text="Binding Title" VerticalAlignment="Center" HorizontalAlignment="Stretch" Foreground="White" />
</BulletDecorator>
</Expander.Header>
<ItemsControl ItemsSource="Binding Options" Background="Transparent" BorderThickness="0">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Label Margin="20,5,5,5" HorizontalAlignment="Stretch">
<Hyperlink TextDecorations="None">
<TextBlock Foreground="White" Text="Binding"/>
</Hyperlink>
</Label>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Expander>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</Window>
我将列表框替换为 ItemsControl。现在唯一不起作用的是一次只能扩展一个扩展器。我想问题是这段代码:
<ItemsControl.Resources>
<Style TargetType="x:Type Expander">
<Setter Property="IsExpanded"
Value="Binding Path=IsSelected, RelativeSource=RelativeSource AncestorType=x:Type ListBoxItem"/>
</Style>
</ItemsControl.Resources>
<ItemsControl.Template>
<ControlTemplate TargetType="x:Type ItemsControl">
<ItemsPresenter/>
</ControlTemplate>
</ItemsControl.Template>
因为它指向 ListBoxItem 类。问题是 ItemsControlItem 类不存在。是现在唯一的问题!!!
【问题讨论】:
这可能更适合CodeReview 或Programmers 但无论如何都会看看,因为这种事情很有趣。 为了隐藏选择,我发现了这个(参见关于设置 ListBoxItem 样式资源的答案的更新部分):***.com/questions/3351904/… 为宽度,在列表框上设置 HorizontalContentAlignment="Center" ---您可能还想在最里面的列表框(子项)上设置 BorderThickness="0" 随时将您的更新移至我的答案中,以使其成为更明确的问答 根据我的发现,ItemsControl 不会跟踪 SelectedItem,而这正是您用作要展开的触发器的内容。 【参考方案1】:可以使用 ViewModel 来完成,然后将 xaml 归结为单个项目作为模板:
为虚拟机设置上下文
<Window.DataContext>
<local:ViewModel />
</Window.DataContext>
快速而肮脏的虚拟机和模型
public class ViewModel
public ObservableCollection<Item> Items get; set;
public ViewModel()
Items = new ObservableCollection<Item>() new Item() Title="Pedidos", ImageSource="Iconos/Pedidos.png", Color=new SolidColorBrush(Colors.OliveDrab), Options = new List<string>()"Nuevo Pedido","Consultar Pedidos","Pedidos Pendientes" ,
new Item() Title="Remitos", ImageSource="Iconos/Remitos.png", Color=new SolidColorBrush(Colors.OrangeRed), Options = new List<string>()"Nuevo Remito","Consultar Remitos","Remitos Pendientes" ,
new Item() Title="Facturas", ImageSource="Iconos/Facturas.png", Color=new SolidColorBrush(Colors.Teal), Options = new List<string>()"Nuevo Factura","Consultar Facturas" ;
public class Item
public string Title get; set;
public List<string> Options get; set;
public SolidColorBrush Color get; set;
public string ImageSource get; set;
然后是 XAML...
物品来源
<ListBox ItemsSource="Binding Items">
项目模板
<ItemsControl.ItemTemplate>
<DataTemplate>
<Expander Margin="2" Width="196" Background="Binding Color">
<Expander.Header>
<BulletDecorator>
<BulletDecorator.Bullet>
<Image Source="Binding ImageSource" Width="64" Height="64" HorizontalAlignment="Left" VerticalAlignment="Top" />
</BulletDecorator.Bullet>
<TextBlock Margin="10,0,0,0" Text="Binding Title" VerticalAlignment="Center" HorizontalAlignment="Stretch" Foreground="White" />
</BulletDecorator>
</Expander.Header>
<ItemsControl ItemsSource="Binding Options" Background="Transparent" BorderThickness="0">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Label Margin="20,5,5,5" HorizontalAlignment="Stretch">
<Hyperlink TextDecorations="None">
<TextBlock Foreground="White" Text="Binding"/>
</Hyperlink>
</Label>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Expander>
</DataTemplate>
</ItemsControl.ItemTemplate>
【讨论】:
这太棒了!特别是因为在我的应用程序中,我正在尝试遵循 MVVM 模式,所以已经有一个 ViewModel!我会试试的,但它看起来很棒!谢谢!!! 我更新您的答案并发布最后一次更新。差不多了!以上是关于WPF 优化 XAML 代码的主要内容,如果未能解决你的问题,请参考以下文章