ericpap
ericpap

Reputation: 2937

WPF Optimize XAML code

Is there a more efficient way of writing following XAML code? (when I say more efficient i meant less repetitive). Especialy with the Hyperlinks and the Expanders. Thank you!

<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>

UPDATE

Ok, i try suggested solution and it work, but there are some small visual differences in the result as can be seen on the then pictures:

Small Differences

On the left the original menú. On the right the new one with the viewModel:

  • Select item get marked, not in the original menu.
  • Width of the expander is too short

This is the result 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>

Can anybody help me tih this? Thanks! UPDATE II

Almost got it!!!

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>

I replace the listbox with ItemsControl. The only thing that is not working now is that only one expander should by expanded at a time. I guess the problem is this code:

         <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>

Because it points to ListBoxItem class. The problem is that ItemsControlItem class doens´t exist. Is the only problem right now!!!

Upvotes: 0

Views: 986

Answers (1)

bdimag
bdimag

Reputation: 963

It could be done with a ViewModel and then xaml is down to a single item as the template:

Setting the context to the VM

<Window.DataContext>
    <local:ViewModel />
</Window.DataContext>

quick and dirty VM and model

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; }

}

and then the XAML...

ItemsSource

<ListBox ItemsSource="{Binding Items}">

ItemTemplate

       <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>

Upvotes: 6

Related Questions