DataGridComboBoxColumn Style - wpf

I wanted to create a combo box column in Data Grid in WPF project. I had a problem to add padding to the cell item (I tried margin instead but it does not highlight the margin when selected). To solve this problem I used following solution to get the demanded effect:
<DataGridTextColumn Header="Saldo"
Binding="{Binding Balance}"
ElementStyle="{StaticResource textBlockColumnElementStyle}"
EditingElementStyle="{StaticResource controlEditingElementStyle}"/>
<DataGridComboBoxColumn Header="Grupa"
DisplayMemberPath="Name"
SelectedValuePath="Id"
SelectedValueBinding="{Binding GroupId}">
<DataGridComboBoxColumn.ElementStyle>
<Style TargetType="ComboBox">
<Setter Property="ItemsSource"
Value="{Binding Path=DataContext.Groups,
RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" />
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Padding="10"
Text="{Binding Name}"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</DataGridComboBoxColumn.ElementStyle>
<DataGridComboBoxColumn.EditingElementStyle>
<Style TargetType="{x:Type ComboBox}">
<Setter Property="ItemsSource"
Value="{Binding Path=DataContext.Groups,
RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" />
</Style>
</DataGridComboBoxColumn.EditingElementStyle>
</DataGridComboBoxColumn>
Now I wanted to create a style in Resources to provide a parametrized template for another columns in the DataGrid (I want to change for example Font only once). But how can I make the styles to be parametrized in place of usage. For example I ItemsSource or Text property in the inner TextBox?

Related

DataGridComboBoxColumn selectItem binding issue

I am trying to create a ComboBox inside a DataGridand to do selectItem binding but when I write this code ,and I select an item in on ComboBox in the column, all the ComboBox items in the DataGrid's column are binding and shows the same selected item. I need to bind each ComboBox item with its selectedItem.
I would be happy to get an help.
this is my code:
<DataGridComboBoxColumn Header="CHOOSE" Width="0.7*"
DisplayMemberPath="Name" SelectedItemBinding="{Binding Path=SelectedReceiver,{RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}">
<DataGridComboBoxColumn.ElementStyle>
<Style TargetType="{x:Type ComboBox}">
<Setter Property="ItemsSource" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}, Path=DataContext.RxList}" />
<Setter Property="ItemTemplate" >
<Setter.Value>
<DataTemplate>
<TextBlock Text="{Binding Path= Name}" Style="{StaticResource GroupBoxHeaderTextBlockStyle}" />
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</DataGridComboBoxColumn.ElementStyle >
<DataGridComboBoxColumn.EditingElementStyle>
<Style TargetType="{x:Type ComboBox}">
<Setter Property="ItemsSource" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}, Path=DataContext.RxList }" />
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Text="{Binding Path= Name}" Style="{StaticResource GroupBoxHeaderTextBlockStyle}"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</DataGridComboBoxColumn.EditingElementStyle>
</DataGridComboBoxColumn>
You bind to DataGrid.ItemsSource.SomeList when you actually need to bind to DataGrid.ItemsSource[x].SomeList.
Basically your list and selected item will always be the same for each column. You can use a static list for your item-model-class (if the list stays the same) and a property for the SelectedItem.
<DataGridComboBoxColumn SelectedItemBinding="{Binding SelectedReceiver}"> <!-- Bind to current item's SelectedReceiver -->
<DataGridComboBoxColumn.ElementStyle>
<Style TargetType="{x:Type ComboBox}">
<Setter Property="ItemsSource" Value="{Binding Path=(modelNamespace:MyModel.RxList)}"/> <!-- Bind to static list property -->
</Style>
</DataGridComboBoxColumn.ElementStyle>
</DataGridComboBoxColumn>

How to get the WPF column binding field from DataGridColumnHeader style

I am doing custom sorting for WPF datagrid (as I use pagination so I can not use default sorting), how can I get name of the field that column binding to? Below is my current code inside DataGrid.Resources
<Style TargetType="DataGridColumnHeader">
<Setter Property="Command" Value="{Binding Path=DataContext.SortCommand, RelativeSource={RelativeSource AncestorType=DataGrid}}"/>
<Setter Property="CommandParameter" Value="{Binding Path=DisplayIndex, RelativeSource={RelativeSource Mode=Self}}"/>
</Style>
I try to get the Column but it return null?
I figured it out, I give the style a key
<DataGrid.Resources>
<Style x:Key="SortableColumnHeader" TargetType="DataGridColumnHeader">
<Setter Property="Command" Value="{Binding Path=DataContext.SortCommand, RelativeSource={RelativeSource AncestorType=DataGrid}}"/>
<Setter Property="CommandParameter" Value="{Binding Path=Column.Binding.Path.Path, RelativeSource={RelativeSource Mode=Self}}"/>
</Style>
</DataGrid.Resources>
and apply it in column's HeaderStyle and it worked
<DataGridTextColumn Binding="{Binding Name}" Header="Column Name" MinWidth="150" HeaderStyle="{StaticResource SortableColumnHeader}"/>

SelectedItem value of combo box gets empty on updating from viewmodel in wpf

I have created a combo box in each datagrid row. The following piece of code is used to create the combo box:
<ComboBox Width="166"
ItemTemplate="{StaticResource GridBinding}"
SelectedItem="{Binding Path=Car, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, IsAsync=True}"
SelectedValue="{Binding Path=Car, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, IsAsync=True}">
<ComboBox.GroupStyle>
<GroupStyle HeaderTemplate="{StaticResource GroupHeader}" />
</ComboBox.GroupStyle>
<ComboBox.Style>
<Style TargetType="ComboBox">
<Setter Property="ItemsSource" Value="{Binding Path=Cars}" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsSelected, RelativeSource={RelativeSource AncestorType=DataGridCell}}" Value="True">
<Setter Property="ItemsSource" Value="{Binding Path=DataContext.GroupedCars, RelativeSource={RelativeSource AncestorType=DataGrid}}" />
</DataTrigger>
</Style.Triggers>
</Style>
</ComboBox.Style>
</ComboBox>
The "Car" property for binding "SelectedItem" in combo box is an object of class "Car" holding some properties like id, name, etc.
The problem I am facing is that when I update the value of "Car" property and call "NotifyPropertyChanged" in its setter, then the value of "SelectedItem" in combo box goes blank/empty.
Please suggest.
The SelectedItem can no longer be found in the Collection (when you update your ItemSource) and gets set to null.
I've simplified your XAML to demonstrate
<ComboBox ItemsSource="{Binding Cars}"
SelectedItem="{Binding Car}">
<ComboBox.Style>
<Style TargetType="ComboBox">
<Style.Triggers>
<Trigger Property="SelectedItem" Value="{x:Null}">
<Setter Property="SelectedIndex" Value="0" />
</Trigger>
</Style.Triggers>
</Style>
</ComboBox.Style>
</ComboBox>
Now the first Item will get selected when you update.

How to bind a property that placed in Viewmodel to each row of Wpf DataGrid?

I need something like EllementStyle and EdititngElementStyle for DataGridTemplateColumn,becasue i want to bind a property to each row of datagrid,and this property is inside ViewModel,i have an instance of this property in viewmodel but need to bind difrenent instance of that to each row!(this property is not in DataGrid.ItemSource)
i did something like this for DataGridTextColumn using EllementStyle and EdititngElementStyle,but it seems DataGridTemplateColumn dosen't have this properties?
any idea?
Edit:
<DataGridTemplateColumn >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding DataContext.MYProperty, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
i did something like this before for DataGridComboBoxColumn and it works.
<DataGridComboBoxColumn
DisplayMemberPath="Name" SelectedValuePath="ID"
SelectedValueBinding="{Binding DocKindID}">
<DataGridComboBoxColumn.ElementStyle>
<Style TargetType="{x:Type ComboBox}">
<Setter Property="ItemsSource" Value="{Binding Path=DataContext.DocKindList, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" />
</Style>
</DataGridComboBoxColumn.ElementStyle>
<DataGridComboBoxColumn.EditingElementStyle>
<Style TargetType="{x:Type ComboBox}">
<Setter Property="ItemsSource" Value="{Binding Path=DataContext.DocKindList, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" />
</Style>
</DataGridComboBoxColumn.EditingElementStyle>
</DataGridComboBoxColumn>

Automatically focusing parts of a ListBoxItem on selection

I have a ListBox which is populated from a collection of ViewModels, which uses in place editing, which I do by having a couple of styles which I can apply to parts of the DataTemplate which make them visible/collapsed as required. These look something like:
<Style
x:Key="UnselectedVisibleStyle"
TargetType="{x:Type FrameworkElement}">
<Setter
Property="Visibility"
Value="{Binding Path=IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}, Converter={StaticResource boolToVis}, ConverterParameter=False}" />
</Style>
<Style
x:Key="SelectedVisibleStyle"
TargetType="{x:Type FrameworkElement}">
<Setter
Property="Visibility"
Value="{Binding Path=IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}, Converter={StaticResource boolToVis}, ConverterParameter=True}" />
</Style>
With my ListBox having it's ItemTemplate given by something like:
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<TextBlock
Text="{Binding Name}"
Style="{StaticResource UnselectedVisibleStyle}" />
<TextBox
x:Name="textBox"
Text="{Binding Name}"
Style="{StaticResource SelectedVisibleStyle}" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
This works fine, but what I want ideally is to have the TextBox automatically selected when a user clicks the item, ideally in a nice generic way I can use throughout my project, and without too much messing around in my codebehind.
Thanks,
DM.
The following change to your selected Style seemed to work for me:
<Style x:Key="SelectedVisibleStyle" TargetType="{x:Type FrameworkElement}">
<Setter Property="Visibility" Value="{Binding Path=IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}, Converter={StaticResource boolToVis}, ConverterParameter=True}"/>
<Style.Triggers>
<Trigger Property="Visibility" Value="Visible">
<Setter Property="FocusManager.FocusedElement" Value="{Binding RelativeSource={RelativeSource Self}}"/>
</Trigger>
</Style.Triggers>
</Style>

Resources