Related
I am currently trying to write a small calendar program in C# WPF.
For the datagrid I have written a userControl.
This works like I want it to work. I will still need to update the optics but for now it is good.
The problem is the code of the DataGridTextColums.. It is all redundant.
So if I want to change something I need to change it everywhere.
<DataGrid x:Name="datagrid"
CanUserAddRows="False"
CanUserDeleteRows="False"
CanUserResizeColumns="False"
CanUserReorderColumns="False"
CanUserResizeRows="False"
CanUserSortColumns="False"
AutoGenerateColumns="False"
SelectionUnit="Cell"
SelectionMode="Extended"
HeadersVisibility="Column"
Background="Transparent"
BorderBrush="Transparent"
ItemsSource="{Binding DataGridSource.DataGridList, RelativeSource={RelativeSource AncestorType=UserControl}}">
<DataGrid.Columns>
<DataGridTextColumn Header="CW" Width="*" IsReadOnly="True" Binding="{Binding CwCell.Text}">
<DataGridTextColumn.CellStyle>
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="Background" Value="{Binding CwCell.BackColor}"/>
<Setter Property="BorderBrush" Value="{Binding CwCell.BorderColor}"/>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="Black"/>
<Setter Property="BorderBrush" Value="OrangeRed"/>
</Trigger>
</Style.Triggers>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
<DataGridTemplateColumn Header="MO" Width="*" IsReadOnly="True">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Border>
<StackPanel Orientation="Horizontal" Background="Transparent">
<TextBlock Text="{Binding MondayCell.Text}" Margin="5,0,0,0" Width="18"/>
<ItemsControl ItemsSource="{Binding Path=MondayCell.Addons}" Margin="0,0,7,0">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Vertical" MaxHeight="20"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Ellipse Width="4" Height="4" Margin="0,1,1,1" Fill="{Binding Color}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Border>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellStyle>
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="Background" Value="{Binding MondayCell.BackColor}"/>
<Setter Property="BorderBrush" Value="{Binding MondayCell.BorderColor}"/>
<Setter Property="ToolTip">
<Setter.Value>
<ToolTip BorderThickness="0" Background="Transparent">
<Grid>
<Border Background="White" BorderBrush="Black" BorderThickness="1">
<StackPanel Orientation="Vertical" DataContext="{Binding MondayCell}">
<TextBlock Text="{Binding AppointmentName}"
Background="White" Width="auto" Margin="5,5,5,1"
TextWrapping="Wrap"
FontWeight="Bold"/>
<Border BorderBrush="Silver" BorderThickness="0,1,0,0" Margin="0,1,0,0" />
<TextBlock Text="{Binding AppointmentDescr}"
Background="White" Margin="5,1,5,5"
TextWrapping="Wrap"/>
<Border BorderBrush="Silver" BorderThickness="0,1,0,0" Margin="0,1,0,0" />
<ItemsControl ItemsSource="{Binding Path=Addons}" Margin="0,0,7,0">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical">
</StackPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Ellipse Width="4" Height="4" Fill="{Binding Color}" Margin="5,0,5,0"/>
<Border BorderBrush="Silver" BorderThickness="1,0,0,0" Margin="0,0,0,0"/>
<TextBlock Text="{Binding Name}" Margin="5,0,0,0"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Border>
</Grid>
</ToolTip>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="Black"/>
<Setter Property="BorderBrush" Value="OrangeRed"/>
</Trigger>
</Style.Triggers>
</Style>
</DataGridTemplateColumn.CellStyle>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="DI" Width="*" IsReadOnly="True">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Border>
<StackPanel Orientation="Horizontal" Background="Transparent">
<TextBlock Text="{Binding TuesdayCell.Text}" Margin="5,0,0,0" Width="18"/>
<ItemsControl ItemsSource="{Binding Path=TuesdayCell.Addons}" Margin="0,0,7,0">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Vertical" MaxHeight="20"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Ellipse Width="4" Height="4" Margin="0,1,1,1" Fill="{Binding Color}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Border>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellStyle>
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="Background" Value="{Binding TuesdayCell.BackColor}"/>
<Setter Property="BorderBrush" Value="{Binding TuesdayCell.BorderColor}"/>
<Setter Property="ToolTip">
<Setter.Value>
<ToolTip BorderThickness="0" Background="Transparent">
<Grid>
<Border Background="White" BorderBrush="Black" BorderThickness="1">
<StackPanel Orientation="Vertical" DataContext="{Binding TuesdayCell}">
<TextBlock Text="{Binding AppointmentName}"
Background="White" Width="auto" Margin="5,5,5,1"
TextWrapping="Wrap"
FontWeight="Bold"/>
<Border BorderBrush="Silver" BorderThickness="0,1,0,0" Margin="0,1,0,0" />
<TextBlock Text="{Binding AppointmentDescr}"
Background="White" Margin="5,1,5,5"
TextWrapping="Wrap"/>
<Border BorderBrush="Silver" BorderThickness="0,1,0,0" Margin="0,1,0,0" />
<ItemsControl ItemsSource="{Binding Path=Addons}" Margin="0,0,7,0">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical">
</StackPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Ellipse Width="4" Height="4" Fill="{Binding Color}" Margin="5,0,5,0"/>
<Border BorderBrush="Silver" BorderThickness="1,0,0,0" Margin="0,0,0,0"/>
<TextBlock Text="{Binding Name}" Margin="5,0,0,0"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Border>
</Grid>
</ToolTip>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="Black"/>
<Setter Property="BorderBrush" Value="OrangeRed"/>
</Trigger>
</Style.Triggers>
</Style>
</DataGridTemplateColumn.CellStyle>
</DataGridTemplateColumn>
<!--same for wednesdayCell to sundayCell-->
</DataGrid.Columns>
</DataGrid>
So as you can see each DataGridTemplateColumn binds to a different Cell (Monday to Sunday).
I tried to create a template out of this. If i keep "MondayCell" in the template (like in the Code below), it works. But obviously I cannot use any other source of data except "MondayCell" then.
See:
<UserControl.Resources>
<DataTemplate x:Key="MyCellTemplate">
<Border>
<StackPanel Orientation="Horizontal" Background="Transparent">
<TextBlock Text="{Binding MondayCell.Text}" Margin="5,0,0,0" Width="18"/>
<ItemsControl ItemsSource="{Binding Path=MondayCell.Addons}" Margin="0,0,7,0">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Vertical" MaxHeight="20"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Ellipse Width="4" Height="4" Margin="0,1,1,1" Fill="{Binding Color}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Border>
</DataTemplate>
<Style TargetType="{x:Type DataGridCell}" x:Key="MyCellStyle">
<Setter Property="Background" Value="{Binding MondayCell.BackColor}"/>
<Setter Property="BorderBrush" Value="{Binding MondayCell.BorderColor}"/>
<Setter Property="ToolTip">
<Setter.Value>
<ToolTip BorderThickness="0" Background="Transparent">
<Grid>
<Border Background="White" BorderBrush="Black" BorderThickness="1">
<StackPanel Orientation="Vertical" DataContext="{Binding MondayCell}">
<TextBlock Text="{Binding AppointmentName}"
Background="White" Width="auto" Margin="5,5,5,1"
TextWrapping="Wrap"
FontWeight="Bold"/>
<Border BorderBrush="Silver" BorderThickness="0,1,0,0" Margin="0,1,0,0" />
<TextBlock Text="{Binding AppointmentDescr}"
Background="White" Margin="5,1,5,5"
TextWrapping="Wrap"/>
<Border BorderBrush="Silver" BorderThickness="0,1,0,0" Margin="0,1,0,0" />
<ItemsControl ItemsSource="{Binding Path=Addons}" Margin="0,0,7,0">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical">
</StackPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Ellipse Width="4" Height="4" Fill="{Binding Color}" Margin="5,0,5,0"/>
<Border BorderBrush="Silver" BorderThickness="1,0,0,0" Margin="0,0,0,0"/>
<TextBlock Text="{Binding Name}" Margin="5,0,0,0"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Border>
</Grid>
</ToolTip>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="Black"/>
<Setter Property="BorderBrush" Value="OrangeRed"/>
</Trigger>
</Style.Triggers>
</Style>
</UserControl.Resources>
Usage in the Datagrid: This works, but only shows the data from MondayCell.
<DataGridTemplateColumn Header="MO" Width="*" IsReadOnly="True">
<DataGridTemplateColumn.CellTemplate>
<StaticResource ResourceKey="MyCellTemplate"/>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellStyle>
<StaticResource ResourceKey="MyCellStyle"/>
</DataGridTemplateColumn.CellStyle>
</DataGridTemplateColumn>
How I want to use it, but doesn't work like this:
Any help is appreciated.
For now I keep it redundant, but I would rather use a template so I only need to change 1 piece of code instead of 7.
Thank you for your help!
I would like to present a solution that is based on using a UserControl:
<DataGridTemplateColumn >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<local:StandardColumn Column="{Binding MondayCell}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<local:StandardColumn Column="{Binding TuesdayCell}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
The StandardColumn implementation , for simplicity , can be as following:
<UserControl x:Class="Problem8.StandardColumn"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Problem8"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800" Name="Parent">
<StackPanel>
<TextBlock Text="{Binding ElementName=Parent,Path=Column}"/>
</StackPanel>
</UserControl>
In this userControl we have a dependency property called Column :
public partial class StandardColumn : UserControl
{
public StandardColumn()
{
InitializeComponent();
}
public static readonly DependencyProperty ColumnProperty =
DependencyProperty.Register("Column", typeof(object), typeof(StandardColumn));
public object Column
{
get { return (object)GetValue(ColumnProperty); }
set { SetValue(ColumnProperty, value); }
}
}
We can also make it even more simple by using the DataContext instead of the Column dependency property.
You could build your columns dynamically using a base string out a txt file and use xamlreader.Parse or persist to disk and then use xamlreader.load.
I answered a similar question a while back but I cannot find the answer.
Create a template as a txt file with placeholders for the parts you want to substitute. Here is the example I use in a sample I wrote:
<?xml version="1.0" encoding="utf-8" ?>
<DataGridTemplateColumn>
<DataGridTemplateColumn.Header>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="xxMMMxx" TextAlignment="Center" Grid.ColumnSpan="2"/>
<TextBlock Text="Units" Margin="2,0,2,0" Grid.Row="1"/>
<TextBlock Text="Value" Margin="2,0,2,0" Grid.Row="1" Grid.Column="2" />
</Grid>
</DataGridTemplateColumn.Header>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding MonthTotals[xxNumxx].Products}" Margin="2,0,2,0" TextAlignment="Right"/>
<TextBlock Text="{Binding MonthTotals[xxNumxx].Total}" Margin="2,0,2,0" TextAlignment="Right" Grid.Column="1"/>
</Grid>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
Make that content, copy if newer and you will get a txt file next to your exe you can read in.
In this I have a dynamic datagrid as another txt file as well, but that is not totally necessary.
Here's my code builds and adds columns.
You could just work with the txt file as a string and do string substitution. This shows manipulating it as xml which has the potential for you to insert xelements etc. It is setting attributes whilst you can maybe forget that part and just do the string substitution, xamlreader.parse into a datagrid column and add to the columns collection.
It is substituting month numbers in the binding for a range of months.
If you consider a rolling last n month financial report, this is the general idea. Last month would be 3 now in april. 4 when you run in may.
private void Button_Click(object sender, RoutedEventArgs e)
{
// Get the datagrid shell
XElement xdg = GetXElement(#"pack://application:,,,/dg.txt");
XElement cols = xdg.Descendants().First(); // Column list
// Get the column template
XElement col = GetXElement(#"pack://application:,,,/col.txt");
DateTime mnth = DateTime.Now.AddMonths(-6);
for (int i = 0; i < 6; i++)
{
DateTime dat = mnth.AddMonths(i);
XElement el = new XElement(col);
// Month in mmm format in header
var mnthEl = el.Descendants("TextBlock")
.Single(x => x.Attribute("Text").Value.ToString() == "xxMMMxx");
mnthEl.SetAttributeValue("Text", dat.ToString("MMM"));
string monthNo = dat.AddMonths(-1).Month.ToString();
// Month as index for the product
var prodEl = el.Descendants("TextBlock")
.Single(x => x.Attribute("Text").Value == "{Binding MonthTotals[xxNumxx].Products}");
prodEl.SetAttributeValue("Text",
"{Binding MonthTotals[" + monthNo + "].Products}");
// Month as index for the total
var prodTot = el.Descendants("TextBlock")
.Single(x => x.Attribute("Text").Value == "{Binding MonthTotals[xxNumxx].Total}");
prodTot.SetAttributeValue("Text",
"{Binding MonthTotals[" + monthNo + "].Total}");
cols.Add(el);
}
string dgString = xdg.ToString();
ParserContext context = new ParserContext();
context.XmlnsDictionary.Add("", "http://schemas.microsoft.com/winfx/2006/xaml/presentation");
context.XmlnsDictionary.Add("x", "http://schemas.microsoft.com/winfx/2006/xaml");
DataGrid dg = (DataGrid)XamlReader.Parse(dgString, context);
Root.Children.Add(dg);
}
private XElement GetXElement(string uri)
{
XDocument xmlDoc = new XDocument();
var xmltxt = Application.GetContentStream(new Uri(uri));
string elfull = new StreamReader(xmltxt.Stream).ReadToEnd();
xmlDoc = XDocument.Parse(elfull);
return xmlDoc.Root;
}
}
You could potentially build out your entire year view using this sort of approach. Build it as xml or a string. Save to disk. xamlreader.load() it back in as controls off disk.
A similar string manipulation based approach would be to build your control as text. Save as a datatemplate in a resource dictionary. You can load such an uncompiled resource dictionary off disk then and just build once a year. You could build centrally in a small utility app intended just for the purpose and distribute to clients.
This is my second solution. I believe that the selection of the DataGrid as a base have created this complexity. Alternatively we can consider more basic controls.
I am drafting the solution:
The MonthView user control may look as following:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<local:HeaderView Grid.Row="0"/>
<ItemsControl ItemsSource="{Binding Weeks}" Grid.Row="1" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:WeekView/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
The WeekView user control may look as following:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<local:DayView DataContext="{Binding CwCell}" Grid.Column="0"/>
<local:DayView DataContext="{Binding MondayCell}" Grid.Column="1"/>
<local:DayView DataContext="{Binding TuesdayCell}" Grid.Column="2"/>
<local:DayView DataContext="{Binding WednesdayCell}" Grid.Column="3"/>
<local:DayView DataContext="{Binding ThursdayCell}" Grid.Column="4"/>
<local:DayView DataContext="{Binding FridayCell}" Grid.Column="5"/>
<local:DayView DataContext="{Binding FridayCell}" Grid.Column="6"/>
<local:DayView DataContext="{Binding SaturdayCell}" Grid.Column="7"/>
<local:DayView DataContext="{Binding SundayCell}" Grid.Column="8"/>
</Grid>
The DayView user control may look as following:
<Border BorderBrush="Black" BorderThickness="1">
<TextBlock Text="{Binding Text}" Width="20" Height="20" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Border>
The HeaderView user control may look as following:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<local:ColumnHeaderView DataContext="CW" Grid.Column="0" />
<local:ColumnHeaderView DataContext="MO" Grid.Column="1" />
<local:ColumnHeaderView DataContext="TU" Grid.Column="2" />
<local:ColumnHeaderView DataContext="WE" Grid.Column="3" />
<local:ColumnHeaderView DataContext="TH" Grid.Column="4" />
<local:ColumnHeaderView DataContext="FR" Grid.Column="5" />
<local:ColumnHeaderView DataContext="SA" Grid.Column="6" />
<local:ColumnHeaderView DataContext="SU" Grid.Column="7" />
</Grid>
The ColumnHeaderView user control may look as following:
<Border BorderBrush="Black" BorderThickness="1">
<TextBlock Text="{Binding }" Width="20" Height="15" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Border>
I have a part of code that makes it so every listbox in my application shows a message when empty.
<Style TargetType="ListBox" BasedOn="{StaticResource {x:Type ListBox}}">
<Style.Triggers>
<Trigger Property="HasItems" Value="False">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<TextBlock FontSize="20" Foreground="{DynamicResource ValidationErrorBrush}"
TextAlignment="Center" Text="Geen data beschikbaar" Width="Auto" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
When I run the application with it enabled (uncommended) the empty listbox indeed display the message.
But when they are filled the item template is wider than it should be.
This is an example where I use a listbox:
<ListBox x:Name="DataGridTraffic"
Grid.Row="1"
SnapsToDevicePixels="True"
ItemsSource="{Binding Path=TrafficJams}"
ScrollViewer.VerticalScrollBarVisibility="Hidden"
SelectedIndex="-1"
ItemTemplate="{DynamicResource TrafficJamDataTemplateShort}"
AlternationCount="2"
BorderThickness="0"
HorizontalContentAlignment="Stretch"
ItemContainerStyle="{DynamicResource MainListBoxStyle}" />
Does anyone have a clue on what is going on?
Edit:
The first image shows how it is when I enable the trigger.
The second shows the way it is supposed to be.
Edit:
Here is some more as asked for.
This is the Datatemplate for the same thing as the pictures.
<DataTemplate x:Key="BusDeparturesDataTemplateShort" DataType="{x:Type model:BusDeparture}">
<Grid>
<Grid.Style>
<Style TargetType="{x:Type Grid}">
<Setter Property="Background" Value="{DynamicResource ValidationErrorLighterBrush}" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=DelayText}" Value="">
<Setter Property="Background" Value="Transparent" />
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Style>
<Grid Margin="4,8,4,4">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="60" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock TextAlignment="Center"
FontWeight="Bold"
FontSize="32"
Text="{Binding Path=DeparturePlatform}"
Grid.Column="0" Margin="0,0,5,0"
HorizontalAlignment="Left"
VerticalAlignment="Center">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=PlatformChanged}" Value="True">
<Setter Property="Foreground" Value="{DynamicResource ValidationErrorBrush}" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=PlatformChanged}" Value="False">
<Setter Property="Foreground" Value="{DynamicResource PrimaryHueMidBrush}" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<Grid Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid>
<StackPanel Orientation="Horizontal"
TextBlock.FontSize="18"
HorizontalAlignment="Left"
VerticalAlignment="Center">
<TextBlock Text="{Binding Path=ServiceNumber}" Width="45" />
<TextBlock Text="{Binding Path=Destination}" />
</StackPanel>
</Grid>
<Grid Grid.Row="1">
<StackPanel Orientation="Horizontal"
TextBlock.FontSize="16"
HorizontalAlignment="Left">
<TextBlock Text="{Binding Path=DepartureTime, StringFormat=HH:mm}" Margin="0,0,4,0" />
<TextBlock Text="{Binding Path=DelayText}" TextAlignment="Right"
Foreground="{DynamicResource ValidationErrorBrush}" />
</StackPanel>
<StackPanel Orientation="Horizontal"
TextBlock.FontSize="16"
HorizontalAlignment="Right">
<TextBlock Text="{Binding Path=Carrier}" TextAlignment="Right"
HorizontalAlignment="Stretch" />
</StackPanel>
</Grid>
</Grid>
</Grid>
</Grid>
</DataTemplate>
And the part where the listbox is in:
<Grid x:Name="MainGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="2*" />
<RowDefinition Height="1*" />
</Grid.RowDefinitions>
<materialDesign:Card Margin="8" Grid.Column="0" Grid.Row="0" VerticalAlignment="Stretch"
materialDesign:ShadowAssist.ShadowDepth="Depth2" x:Name="CardTrain">
...
</materialDesign:Card>
<materialDesign:Card Margin="8" Grid.Row="0" Grid.Column="1" VerticalAlignment="Stretch"
materialDesign:ShadowAssist.ShadowDepth="Depth2" x:Name="CardBus">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition />
</Grid.RowDefinitions>
<Border BorderBrush="{DynamicResource MaterialDesignDivider}" BorderThickness="0,0,0,1">
<TextBlock Text="Bustijden" Foreground="{DynamicResource PrimaryHueDarkBrush}"
TextAlignment="Center"
FontSize="36" FontWeight="ExtraBold" />
</Border>
<ListBox x:Name="DataGridBus"
Grid.Row="1"
SnapsToDevicePixels="True"
ItemsSource="{Binding Path=BusDepartures}"
ScrollViewer.VerticalScrollBarVisibility="Hidden"
SelectedIndex="-1"
ItemTemplate="{DynamicResource BusDeparturesDataTemplateShort}"
AlternationCount="2"
BorderThickness="0"
HorizontalContentAlignment="Stretch"
ItemContainerStyle="{DynamicResource MainListBoxStyle}"
VerticalAlignment="Top" />
</Grid>
</materialDesign:Card>
<materialDesign:Card Margin="8" Grid.Row="0" Grid.Column="2" VerticalAlignment="Stretch"
materialDesign:ShadowAssist.ShadowDepth="Depth2" x:Name="CardTraffic">
...
</materialDesign:Card>
<materialDesign:Card Margin="8" Grid.Row="0" Grid.Column="3" VerticalAlignment="Stretch"
materialDesign:ShadowAssist.ShadowDepth="Depth2" x:Name="CardTwitter">
...
</materialDesign:Card>
<materialDesign:Card Margin="8" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="4"
VerticalAlignment="Stretch" materialDesign:ShadowAssist.ShadowDepth="Depth2"
x:Name="CardNews">
...
</materialDesign:Card>
</Grid>
I have a list box binds to a ObservableCollection of Items. Each listboxItem contains a few textblocks and a few buttons. I would like to show the buttons inside the listboxItem only when the listbox item is selected or hightlight. If the listbox item is not highlighted, the button should be hidden. I tried to use datatrigger to bind to the IsSelected property. However it does not work. Please advice. thanks
<ListBox Name="LayoutListBox" SelectedItem="{Binding Path=SelectedLayout, Mode=TwoWay}" ItemsSource="{Binding Layouts}" SelectionMode="Single" HorizontalContentAlignment="Stretch">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="Gray"/>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Gray"/>
</Style.Resources>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Border HorizontalAlignment="Stretch" Margin="2" CornerRadius="2" BorderBrush="#80808080" BorderThickness="1" Background="GhostWhite">
<Grid>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height ="*"/>
<RowDefinition Height ="*"/>
</Grid.RowDefinitions>
<DockPanel Grid.Row="1" Grid.Column="3" DockPanel.Dock="Right">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Visibility="{Binding Path=ViewName, Converter={StaticResource Converter}, ConverterParameter=false}">
<Button ToolTip="Save">
<Image Source="/Common.View;component/LayoutManager/View/Images/PushPin.png" />
</Button>
<Button Click="EditButtonClick" ToolTip="Edit">
<Image Source="/Common.View;component/LayoutManager/View/Images/pencil.png" />
</Button>
<Button Click="DeleteButtonClick" ToolTip="Delete">
<Image Source="/Common.View;component/LayoutManager/View/Images/cross.png" />
</Button>
</StackPanel>
</DockPanel>
</Grid>
</DockPanel>
</Grid>
</Border>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I attached a simple example to show button in listbox item when you selected. it should have to bind as RelativeSource and have to use Converter
Example:
<Window.Resources>
<BooleanToVisibilityConverter x:Key="booleanVisibleConverter" />
</Window.Resources>
<Grid>
<ListBox ItemsSource="{Binding ObservableCollection}" Grid.Row="0" SelectedItem="{Binding Path=Item}"
SelectionMode="Single" IsSynchronizedWithCurrentItem="True" Margin="1" ScrollViewer.HorizontalScrollBarVisibility="Disabled" SelectedIndex="0">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Label Content="{Binding}" />
<Button Content=" X " Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}, Path=IsSelected, Converter={StaticResource booleanVisibleConverter}}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
You can create a style to associate with each of your buttons as follows:
<Style TargetType="{x:Type Button}">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource
Mode=FindAncestor, AncestorType={x:Type ListBoxItem}},
Path=IsSelected}" Value="True">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
I have a design for my user control. The control contains many rows and columns and inside it has sub-grids and rows and columns. One of the inner most row contains a ListView whose Horizontal and Vertical Scroll bar set to Auto.
I am able to view Horizontal Scroll bar for listview as well as the outer most grid, but I am unable to view Vertical Scroll bar for listview, but for the outer grid is working fine.
Here is the xaml for the same.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Orientation="Horizontal" VerticalAlignment="Center" Margin="8,0,0,0">
<Image Source="pack://application:,,,/EMC.DD.CommonFrameworkLayer;component/Images/Items1.png" Width="50" Height="50"></Image>
<TextBlock Text="Items" VerticalAlignment="Center" Style="{StaticResource DashboardTextBlockStyle}" Margin="8,0,0,0" ></TextBlock>
</StackPanel>
<StackPanel Orientation="Horizontal" Grid.Row="1" Background="#eaeaea" Margin="8,0,0,0">
<Image Source="pack://application:,,,/EMC.DD.CommonFrameworkLayer;component/Images/HomeDashBoard.png"></Image>
<TextBlock Text="DashBoard" Style="{StaticResource HomeDashBoardTextBlockStyle}" VerticalAlignment="Center" Margin="8,0,0,0"></TextBlock>
<TextBlock Text=">" VerticalAlignment="Center" Margin="5,0,0,0" Style="{StaticResource HomeDashBoardTextBlockStyle}" FontWeight="Medium"></TextBlock>
<TextBlock Text="Items" VerticalAlignment="Center" Margin="5,0,0,0" Style="{StaticResource HomeDashBoardTextBlockStyle}" FontWeight="Medium"></TextBlock>
<TextBlock x:Name="ItemsTextBlock" x:FieldModifier="private" Margin="5,0,0,0" VerticalAlignment="Center"></TextBlock>
</StackPanel>
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto" Grid.Row="2" Grid.Column="0">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Orientation="Horizontal" VerticalAlignment="Center" Margin="8,10,0,10">
<TextBox x:Name="ItemTextBox" MinWidth="160" Height="25">
</TextBox>
</StackPanel>
<StackPanel Grid.Row="1" Orientation="Horizontal" VerticalAlignment="Center" Margin="8,2,0,10">
<ComboBox x:Name="CategoryComboBox" DisplayMemberPath="CategoryName" SelectedValue="CategoryID" SelectedValuePath="CategoryName"
Margin="2,2,0,3" MinHeight="27" MinWidth="250" Grid.Row="2" Grid.Column="2" HorizontalAlignment="Left" Grid.ColumnSpan="2" SelectedIndex="-1"/>
<Button Style="{StaticResource CRUDButtonStyle}" Content="Search" Margin="5,0,0,0" Click="SearchButton_Click"></Button>
<StackPanel Orientation="Horizontal" Margin="150,0,0,0">
<Button Style="{StaticResource CRUDButtonStyle}" Content="New Item" Click="ItemButton_Click" ></Button>
<Button Style="{StaticResource CRUDButtonStyle}" Content="Delete Item" Margin="5,0,0,0" Click="DeleteButton_Click"></Button>
<Button Style="{StaticResource CRUDButtonStyle}" Content="Delete All" Margin="2,0,0,0" Click="DeleteAllItem_Click"></Button>
</StackPanel>
</StackPanel>
<Grid Grid.Row="2" Margin="8,0,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="900"/>
<ColumnDefinition Width="Auto" MinWidth="200"/>
</Grid.ColumnDefinitions>
<Grid Grid.Column="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*"/>
<RowDefinition Height="10" />
</Grid.RowDefinitions>
<Border Grid.Row="0" Style="{StaticResource DefaultBorderStyle}">
<StackPanel Grid.Row="0" Orientation="Horizontal" VerticalAlignment="Top" Margin="0,0,0,0">
<Image Source="pack://application:,,,/EMC.DD.CommonFrameworkLayer;component/Images/Items1.png"></Image>
<TextBlock Text="List Of Items" Margin="5,0,0,0" VerticalAlignment="Center"
Style="{StaticResource HomeDashBoardTextBlockStyle}" FontWeight="Normal"/>
</StackPanel>
</Border>
<ListView x:Name="ItemsListView" x:FieldModifier="private" Grid.Row="1" MouseDown="ListViewItem_PreviewMouseDown"
SelectionChanged="ListView_SelectionChanged" ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Auto">
<ListView.Resources>
<Style TargetType="{x:Type GridViewColumnHeader}" x:Key="MyHeaderStyle">
<Setter Property="FontFamily" Value="Segoe UI Light"/>
<Setter Property="FontWeight" Value="DemiBold"></Setter>
<Setter Property="Height" Value="30"></Setter>
</Style>
<local:IntToBoolConverter x:Key="IntBoolKey"></local:IntToBoolConverter>
<Style x:Key="TextStyle" TargetType="{x:Type TextBlock}">
<EventSetter Event="Hyperlink.Click" Handler="EditClicked" />
</Style>
<local:BackgroundConverter x:Key="BackgroundKey"/>
<Style x:Key="columnHeaderContianerStyle" TargetType="ListViewItem">
<Setter Property="Background">
<Setter.Value>
<Binding RelativeSource="{RelativeSource Self}" Converter="{StaticResource BackgroundKey}"/>
</Setter.Value>
</Setter>
<!--<EventSetter Event="PreviewMouseDown" Handler="ListViewItem_PreviewMouseDown"></EventSetter>-->
</Style>
<Style x:Key="myHeaderStyle" TargetType="{x:Type GridViewColumnHeader}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="False">
<Setter Property="Background" Value="#1570a6"/>
<Setter Property="Foreground" Value="#FFFFFF"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="#000000"/>
</Trigger>
</Style.Triggers>
</Style>
</ListView.Resources>
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}" BasedOn="{StaticResource columnHeaderContianerStyle}">
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Style.Triggers>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter Property="IsSelected" Value="True" />
</Trigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>
<ListView.View>
<GridView AllowsColumnReorder="true" ColumnHeaderContainerStyle="{StaticResource MyHeaderStyle}">
<GridViewColumn Width="50" HeaderContainerStyle="{StaticResource myHeaderStyle}">
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox Width ="20" Height="20" IsChecked="{Binding Path=IsActive,Converter={StaticResource IntBoolKey}}"></CheckBox>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Item ID" Width="110" DisplayMemberBinding="{Binding Path=ItemID,Mode=OneWay}"
HeaderContainerStyle="{StaticResource myHeaderStyle}"/>
<GridViewColumn Header="Item Name" Width="200" DisplayMemberBinding="{Binding Path=ItemName,Mode=OneWay}"
HeaderContainerStyle="{StaticResource myHeaderStyle}"/>
<GridViewColumn Header="Item Price" Width="200" DisplayMemberBinding="{Binding Path=Price,Mode=OneWay}"
HeaderContainerStyle="{StaticResource myHeaderStyle}" >
</GridViewColumn>
<GridViewColumn Header="Category" Width="200" DisplayMemberBinding="{Binding Path=Category.CategoryName,Mode=OneWay}"
HeaderContainerStyle="{StaticResource myHeaderStyle}"/>
<GridViewColumn Header="Item Image" Width="200" HeaderContainerStyle="{StaticResource myHeaderStyle}">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Image Width="100" Height="50" VerticalAlignment="Center" HorizontalAlignment="Center"
Source="{Binding Path=ItemImagePath,Mode=OneWay}"></Image>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Width="100" HeaderContainerStyle="{StaticResource myHeaderStyle}">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Name="urlToContent" MinWidth="150" Width="Auto" Style="{StaticResource TextStyle}">
<Hyperlink NavigateUri="{Binding Path=URL}" Name="hlkURL">
<TextBlock Text="Edit" HorizontalAlignment="Center"/>
</Hyperlink>
</TextBlock>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
</Grid>
<Grid Grid.Column="1">
<GroupBox x:Name="ItemDetails" Header="Item Details" FontFamily="Segoe UI" HorizontalAlignment="Center" Margin="2,-10,0,0"
VerticalAlignment="Top" Height="Auto" Width="Auto" Grid.Row="0">
<Grid Margin="2,5,0,0" HorizontalAlignment="Center">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0" HorizontalAlignment="Center">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10" />
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="Item Name" FontFamily="Segoe UI" VerticalAlignment="Center" HorizontalAlignment="Right" Grid.Row="0" Grid.Column="1"
Margin="0,0,0,5"/>
<TextBlock x:Name="ItemNameTextBlock" Text="{Binding Path=ItemName,Mode=OneWay}" FontFamily="Segoe UI" FontWeight="DemiBold" VerticalAlignment="Top"
HorizontalAlignment="Left" Grid.Row="0" Grid.Column="2" Margin="5,0,0,0"/>
<TextBlock Text="Category" FontFamily="Segoe UI" VerticalAlignment="Center" HorizontalAlignment="Right" Grid.Row="1" Grid.Column="1"
Margin="0,0,0,5"></TextBlock>
<TextBlock x:Name="CategoryTextBlock" Text="{Binding Path=Category.CategoryName,Mode=OneWay}" FontFamily="Segoe UI" FontWeight="DemiBold" VerticalAlignment="Top"
HorizontalAlignment="Left" Grid.Row="1" Grid.Column="2" Margin="5,0,0,0"/>
<TextBlock Text="Item Quantity" FontFamily="Segoe UI" VerticalAlignment="Center" HorizontalAlignment="Right" Grid.Row="2" Grid.Column="1"
Margin="0,0,0,5"></TextBlock>
<TextBlock x:Name="ItemQuantityTextBlock" Text="{Binding Path=ItemQuantity,Mode=OneWay}" FontFamily="Segoe UI" FontWeight="DemiBold" VerticalAlignment="Top"
HorizontalAlignment="Left" Grid.Row="2" Grid.Column="2" Margin="5,0,0,0"/>
</Grid>
<ListView x:Name="ItemIngredientsListView" Grid.Row="1" Margin="2,0,0,5" ScrollViewer.HorizontalScrollBarVisibility="Auto"
ScrollViewer.VerticalScrollBarVisibility="Auto">
<ListView.Resources>
<Style TargetType="{x:Type GridViewColumnHeader}" x:Key="MyHeaderStyle">
<Setter Property="FontFamily" Value="Segoe UI Light"/>
<Setter Property="FontWeight" Value="DemiBold"></Setter>
<Setter Property="Height" Value="30"></Setter>
</Style>
<Style x:Key="myHeaderStyle" TargetType="{x:Type GridViewColumnHeader}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="False">
<Setter Property="Background" Value="#1570a6"/>
<Setter Property="Foreground" Value="#FFFFFF"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="#000000"/>
</Trigger>
</Style.Triggers>
</Style>
<local:BackgroundConverter x:Key="BackgroundKey"/>
<Style x:Key="columnHeaderContianerStyle" TargetType="ListViewItem">
<Setter Property="Background">
<Setter.Value>
<Binding RelativeSource="{RelativeSource Self}" Converter="{StaticResource BackgroundKey}"/>
</Setter.Value>
</Setter>
<!--<EventSetter Event="PreviewMouseDown" Handler="ListViewItem_PreviewMouseDown"></EventSetter>-->
</Style>
</ListView.Resources>
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}" BasedOn="{StaticResource columnHeaderContianerStyle}">
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Style.Triggers>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter Property="IsSelected" Value="True" />
</Trigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>
<ListView.View>
<GridView AllowsColumnReorder="true" ColumnHeaderContainerStyle="{StaticResource MyHeaderStyle}">
<GridViewColumn Header="Ingredient ID" Width="80" DisplayMemberBinding="{Binding Path=ItemIngredientID,Mode=OneWay}"
HeaderContainerStyle="{StaticResource myHeaderStyle}"/>
<GridViewColumn Header="Ingredient" Width="200" DisplayMemberBinding="{Binding Path=IngredientName,Mode=OneWay}"
HeaderContainerStyle="{StaticResource myHeaderStyle}"/>
</GridView>
</ListView.View>
</ListView>
</Grid>
</GroupBox>
</Grid>
</Grid>
</Grid>
</ScrollViewer>
</Grid>
May be I am posting huge xaml, because I am not sure where exactly went wrong in the whole user control.
Some one, please look into my xaml and tell me where exactly do I need to change the rowHeight or some thing else.
Any help highly appreciated.
The ScrollViewer of WPF provides unlimited space to its child element - I think that is what hinders you to see the vertical scroll bar of your ListView. Let's analyze your situation:
The scroll viewer provides unlimited space to its child grid (let's call it A).
A is divided into three rows: the first two rows' height will be calculated according to the content they display (<RowDefinition Height="Auto" />). The last row will take the remaining infinite space provided by the scroll viewer.
In this last row, another grid is placed (let's call it B) that has two columns and three rows. The second row takes the remaining space (still infinite) because its height is set to *.
In this very row, your list view is placed. This means that it has unlimited vertical space within the WPF layout system and has no need to show its vertical scroll bar.
A solution might be to limit the height of this row but provide a GridSplitter so that the user is able to change the height. Another solution as pointed out by #pushpraj (while I was writing this) is to limit the height of the list view.
If you have any further questions, please feel free to ask.
I have a ListBox which is bound to my custom class
ObservableCollection<FieldPropertyItem> _fieldOrderCollection`;
internal struct FieldPropertyItem
{
public string Name { get; set; }
public string AliasName { get; set; }
}
Code for ListBox:
<ListBox x:Name="FieldOrderListBox" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" HorizontalContentAlignment="Stretch" SelectedIndex="0"
ScrollViewer.VerticalScrollBarVisibility="Auto" SelectionChanged="FieldOrderListBox_SelectionChanged">
<ListBox.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="#FF479EF3"></SolidColorBrush>
</ListBox.Resources>
<ListBox.ItemTemplate>
<DataTemplate x:Name="MyTemplate">
<Grid Margin="-5,-1,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="FieldName" MinWidth="5" MaxWidth="300"/>
<ColumnDefinition Width="2" />
<ColumnDefinition Width="*" MaxWidth="350"/>
</Grid.ColumnDefinitions>
<Border BorderBrush="Black" Grid.Column="0" BorderThickness="0.5,0.0,0.5,0.5" IsHitTestVisible="False">
<TextBlock Text="{Binding Name}" Grid.Column="0" ToolTip="{Binding Name}" Margin="2,0,2,0" VerticalAlignment="Center"/>
</Border>
<GridSplitter Grid.Column="1" Width="2" HorizontalAlignment="Left" Background="Black" Margin="-2,0,-1,0"/>
<Border BorderBrush="Black" BorderThickness="0,0.0,0.5,0.5" Margin="-2,0,0,0" Padding="0,5,0,0" Grid.Column="2">
<TextBlock Text="{Binding AliasName}" Grid.Column="1" ToolTip="{Binding AliasName}" Margin="2,0,2,0" VerticalAlignment="Center" HorizontalAlignment="Stretch"/>
</Border>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Now i want that my ListBox first item should look like header. The remaining ones should have a light dim background.
You can check if the previous item is null using a RelativeSource binding in a trigger, e.g. this DataTemplate makes the first element bold:
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="A" />
<ColumnDefinition SharedSizeGroup="B" />
</Grid.ColumnDefinitions>
<Grid.Style>
<Style TargetType="{x:Type Grid}">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource PreviousData}}" Value="{x:Null}">
<Setter Property="TextElement.FontWeight" Value="Bold" />
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Style>
<TextBlock Grid.Column="0" Text="{Binding Name}" />
<TextBlock Grid.Column="1" Text="{Binding AliasName}" />
</Grid>
</DataTemplate>
(Use shared size groups as shown above to align the grids with one-another, set Grid.IsSharedSizeGroup to true on the ListBox element)
I would not recommend doing this by the way, if your item collection contains the header there is definitely something wrong with your data-design.
1.) You can have a new Property IsFirstItem on your FieldPropertyItem
Whenever your _fieldOrderCollection changes determine the IsFirtItem Property of the elements in your ObservableCollection.
2.) Define the corresponding Templates in XAML (Normal and FirstItem Template)
3.) You can then bind in XAML like this:
<ListBox ItemsSource="{Binding Items}" >
<ListBox.ItemTemplate>
<DataTemplate>
<ContentControl x:Name="contentControl" Content="{Binding}" ContentTemplate="{StaticResource normalTemplate}"/>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Path=IsFirstItem}" Value="True" >
<Setter TargetName="contentControl" Property="ContentTemplate" Value="{StaticResource firstItemTemplate}"></Setter>
</DataTrigger>
</DataTemplate.Triggers>
</ListBox.ItemTemplate>
</ListBox>