I have this code that works,
private void TreeSetup_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
if (sender is TreeViewItem)
{
((TreeViewItem)sender).IsSelected = true;
}
e.Handled = true;
}
private void TreeSetup_MouseRightButtonUp(object sender, MouseButtonEventArgs e)
{
ContextMenu PopupMenu = this.FindResource("cmButton") as ContextMenu;
if (TreeSetup.SelectedItem != null)
{
PopupMenu.PlacementTarget = sender as TreeViewItem;
PopupMenu.IsOpen = true;
}
}
But once I add this ItemContainerStyle,
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay}" />
<Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}"/>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="FontWeight" Value="Bold" />
</Trigger>
</Style.Triggers>
</Style>
</TreeView.ItemContainerStyle>
My sender on the mouse down event becomes a TreeView instead of TreeViewItem.
Does anyone know the cause and fix to this?
I binded the mousedown event under the ItemContainerStyle:
<TreeView.ItemContainerStyle>
<Style TargetType="TreeViewItem">
<EventSetter Event="MouseRightButtonDown" Handler="TreeSetup_MouseRightButtonDown"/>
<Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay}" />
<Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}"/>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="FontWeight" Value="Bold" />
</Trigger>
</Style.Triggers>
</Style>
</TreeView.ItemContainerStyle>
Related
I have a scenario where two lists are to be shown in one window, but user can select in any one of the list only and proceed.
Lets say listbox1 and listbox2 if user select an item in listbox1 and again select from listbox2 the selected item in listbox1 should be removed.
I have to achieve this only through xaml not from codebehind. so I tried below:
<Grid.Resources>
<Storyboard x:Key="temp" >
<Int32Animation Storyboard.TargetName="lstbox" Storyboard.TargetProperty="(ListBox.SelectedIndex)"
To="-1" Duration="0:0:.2" />
</Storyboard>
<Storyboard x:Key="temp1" >
<Int32Animation Storyboard.TargetName="listBox1" Storyboard.TargetProperty="(ListBox.SelectedIndex)"
To="-1" Duration="0:0:.2" />
</Storyboard>
</Grid.Resources>
As above created two storyboards to set selectedIndex to -1 and called that story board when selection changed event trigger as shown below:
<ListBox Name="listBox1" HorizontalAlignment="Left" Grid.Column="1">
<ListBox.Triggers>
<EventTrigger RoutedEvent="ListBox.SelectionChanged">
<BeginStoryboard Storyboard="{StaticResource temp}"/>
</EventTrigger>
</ListBox.Triggers>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Background" Value="AliceBlue" />
<Setter Property="BorderBrush" Value="BlanchedAlmond" />
<Setter Property="BorderThickness" Value="2" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
<ListBoxItem Content="Coffie"></ListBoxItem>
<ListBoxItem Content="Tea"></ListBoxItem>
<ListBoxItem Content="Orange Juice"></ListBoxItem>
<ListBoxItem Content="Milk"></ListBoxItem>
<ListBoxItem Content="Iced Tea"></ListBoxItem>
<ListBoxItem Content="Mango Shake"></ListBoxItem>
</ListBox>
<ListBox Name="lstbox" ItemsSource="{Binding MyData}" Grid.Column="1" Grid.Row="1" SelectionChanged="lstbox_SelectionChanged">
<ListBox.Triggers>
<EventTrigger RoutedEvent="ListBox.SelectionChanged">
<BeginStoryboard Storyboard="{StaticResource temp1}"/>
</EventTrigger>
</ListBox.Triggers>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Background" Value="AliceBlue" />
<Setter Property="BorderBrush" Value="BlanchedAlmond" />
<Setter Property="BorderThickness" Value="2" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="DarkViolet" />
</Trigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
Through code behind when I set SelectedIndex to -1 styles for selectedItem are clearing but through storyboard the styles are not clearing.
Please tell anyother way or guide me to make it work.
I have to achieve it only through xaml.
Thanks,
Nagasree.
Based on your sample, if you change your storyboards like so, it will work:
<Storyboard x:Key="temp">
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="lstbox"
Storyboard.TargetProperty="SelectedItem">
<ObjectAnimationUsingKeyFrames.KeyFrames>
<DiscreteObjectKeyFrame
KeyTime="0:0:0"
Value="null" />
</ObjectAnimationUsingKeyFrames.KeyFrames>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="temp1">
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="listBox1"
Storyboard.TargetProperty="SelectedItem">
<ObjectAnimationUsingKeyFrames.KeyFrames>
<DiscreteObjectKeyFrame
KeyTime="0:0:0"
Value="null" />
</ObjectAnimationUsingKeyFrames.KeyFrames>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
However, like commenters mentioned. If you are using MVVM and databinding to SelectedItem, etc., this may not work.
If your boss will let you use a Behavior, you can do something like this:
<ListBox
Name="ListBox1"
ItemsSource="{Binding MyData1}"
SelectedItem="{Binding SelectedMyData1, Mode=TwoWay}">
<i:Interaction.Behaviors>
<local:ListBoxSingleSelectionBehavior TargetListBox="{Binding ElementName=ListBox2}" />
</i:Interaction.Behaviors>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Background" Value="AliceBlue" />
<Setter Property="BorderBrush" Value="BlanchedAlmond" />
<Setter Property="BorderThickness" Value="2" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
<ListBox
Name="ListBox2"
ItemsSource="{Binding MyData2}"
SelectedItem="{Binding SelectedMyData2, Mode=TwoWay}">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Background" Value="AliceBlue" />
<Setter Property="BorderBrush" Value="BlanchedAlmond" />
<Setter Property="BorderThickness" Value="2" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="DarkViolet" />
</Trigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
And here is the behavior:
using System.Windows;
using System.Windows.Controls;
using Microsoft.Xaml.Behaviors;
namespace SO
{
public class ListBoxSingleSelectionBehavior : Behavior<ListBox>
{
private bool isSelectionChanging;
public ListBoxSingleSelectionBehavior()
{
}
#region TargetListBox (DependencyProperty)
/// <summary>
/// Identifies the TargetListBox property.
/// </summary>
public static readonly DependencyProperty TargetListBoxProperty =
DependencyProperty.Register(
"TargetListBox",
typeof(ListBox),
typeof(ListBoxSingleSelectionBehavior),
new PropertyMetadata(null, OnTargetListBoxChanged));
/// <summary>
/// Gets or sets the target ListBox to monitor.
/// </summary>
public ListBox TargetListBox
{
get => (ListBox)GetValue(TargetListBoxProperty);
set => SetValue(TargetListBoxProperty, value);
}
private static void OnTargetListBoxChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var behavior = (ListBoxSingleSelectionBehavior) d;
var oldTargetListBox = (ListBox) e.OldValue;
var newTargetListBox = (ListBox) e.NewValue;
behavior.OnTargetListBoxChanged(oldTargetListBox, newTargetListBox);
}
private void OnTargetListBoxChanged(ListBox oldTargetListBox, ListBox newTargetListBox)
{
if (oldTargetListBox != null)
{
oldTargetListBox.SelectionChanged -= OnTargetSelectionChanged;
}
if (newTargetListBox != null)
{
newTargetListBox.SelectionChanged += OnTargetSelectionChanged;
}
}
#endregion
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.SelectionChanged += OnSourceSelectionChanged;
}
protected override void OnDetaching()
{
base.OnDetaching();
if (AssociatedObject != null)
{
AssociatedObject.SelectionChanged -= OnSourceSelectionChanged;
}
}
private void OnSourceSelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (isSelectionChanging) return;
isSelectionChanging = true;
if (TargetListBox != null)
{
TargetListBox.SelectedItem = null;
}
isSelectionChanging = false;
}
private void OnTargetSelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (isSelectionChanging) return;
isSelectionChanging = true;
if (AssociatedObject != null)
{
AssociatedObject.SelectedItem = null;
}
isSelectionChanging = false;
}
}
}
I need to be able to distinguish from which column in a DataGrid, a TextBox has been edited:
<DataGridTextColumn Header="No" Binding="{Binding NumberOfItems}">
<DataGridTextColumn.EditingElementStyle>
<Style TargetType="{x:Type TextBox}" x:Name="NumOfItems">
<Setter Property="MaxLength" Value="2"/>
</Style>
</DataGridTextColumn.EditingElementStyle>
</DataGridTextColumn>
<DataGridTextColumn Header="Role" Binding="{Binding Role}" Width="0.75*">
<DataGridTextColumn.EditingElementStyle>
<Style TargetType="{x:Type TextBox}" x:Name="Role">
<Setter Property="MaxLength" Value="30"/>
</Style>
</DataGridTextColumn.EditingElementStyle>
</DataGridTextColumn>
so that I can update a database with the correct information. I have tried to use x:Name but, with the code below, the name is always empty
private void dgItems_CellEditEnding(object sender,
DataGridCellEditEndingEventArgs e)
{
if(e.EditingElement is TextBox)
{
TextBox t = e.EditingElement as TextBox;
..........
if (t.Name == "Role")
//do this
else if (t.NumOfItems)
//do this
}
Thanks for any help
You could set the Tag property in the Style:
<Style TargetType="{x:Type TextBox}">
<Setter Property="MaxLength" Value="30"/>
<Setter Property="Tag" Value="Role"/>
</Style>
if (t.Tag?.ToString() == "Role")
I have a customized ComboBox to handle the text input and filter the itemsource. The problem I'm having is when I open the ComboBox the textBox is focused and let me write in it, then if I close and open it again, the TextBox is not focused and I cant write anything inside. I've discovered that the first time the comboBox is opening it is setting the focus on the TextBox but when I close it the TextBox keeps its IsFocused property true so when reopening the problem happens. It's just when opening and reopening clicking the comboBox because if I click outside the ComboBox to close it and then open it again everything works nice.
Here is the customized style I wrote and the ComboBox I'm using.
<Style x:Key="FilteringComboBox" TargetType="ComboBox">
<Setter Property="SnapsToDevicePixels" Value="true" />
<Setter Property="OverridesDefaultStyle" Value="true" />
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto" />
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Visible" />
<Setter Property="ScrollViewer.CanContentScroll" Value="true" />
<Setter Property="IsEditable" Value="True"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="FontFamily" Value="Coves"/>
<Setter Property="FontWeight" Value="Normal"/>
<Setter Property="FontSize" Value="12"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ComboBox">
<Border x:Name="TopBorder"
CornerRadius="8"
BorderBrush="Grey"
BorderThickness="1"
Padding="10,0,1,0">
<Border.Background>
<LinearGradientBrush EndPoint="0.504,1.5" StartPoint="0.504,0.03">
<GradientStop Color="White" Offset="0"/>
<GradientStop Color="#e3e3e5" Offset="0.65"/>
</LinearGradientBrush>
</Border.Background>
<Grid>
<ToggleButton
Name="ToggleButton"
Template="{DynamicResource FilteringComboBoxToggleButton}"
Grid.Column="2"
Focusable="false"
IsChecked="{Binding Path=IsDropDownOpen,Mode=TwoWay,RelativeSource={RelativeSource TemplatedParent}}"
ClickMode="Press">
</ToggleButton>
<TextBlock Name="ContentSite" IsHitTestVisible="False"
Text="{Binding Source={StaticResource Proxy}, Path=Data.Name, UpdateSourceTrigger=PropertyChanged}"
Visibility="Visible" Foreground="#37465c"
Padding="3,3,23,3" VerticalAlignment="Center"
HorizontalAlignment="Left" />
<TextBox x:Name="PART_EditableTextBox" MaxWidth="215" MinWidth="100"
Text="{Binding Source={StaticResource Proxy}, Path=Data.FilterText, UpdateSourceTrigger=PropertyChanged}"
Foreground="#37465c"
HorizontalAlignment="Left" VerticalAlignment="Center" Margin="3,3,23,3" Focusable="True" Background="Transparent"
Visibility="Collapsed"/>
<Popup x:Name="Popup" Placement="Bottom" IsOpen="{TemplateBinding IsDropDownOpen}" AllowsTransparency="True"
Focusable="False" PopupAnimation="Fade">
<StackPanel Orientation="Vertical" Width="215">
<Grid Name="DropDown" SnapsToDevicePixels="True"
MaxHeight="{TemplateBinding MaxDropDownHeight}">
<Border x:Name="DropDownBorder" BorderThickness="1"
BorderBrush="#888">
<Border.Background>
<LinearGradientBrush EndPoint="0.504,1.5" StartPoint="0.504,0.03">
<GradientStop Color="White" Offset="0"/>
<GradientStop Color="#e3e3e5" Offset="0.65"/>
</LinearGradientBrush>
</Border.Background>
<ScrollViewer Margin="0" SnapsToDevicePixels="True">
<StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Contained"/>
</ScrollViewer>
</Border>
</Grid>
</StackPanel>
</Popup>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Cursor" Value="Hand"/>
</Trigger>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter Property="IsDropDownOpen" Value="True"/>
<Setter TargetName="PART_EditableTextBox" Property="Visibility" Value="Visible" />
<Setter TargetName="ContentSite" Property="Visibility" Value="Collapsed" />
<Setter Property="IsEditable" Value="True"/>
</Trigger>
<Trigger Property="IsMouseCaptured" Value="False">
<Setter Property="IsDropDownOpen" Value="False"/>
<Setter TargetName="PART_EditableTextBox" Property="Visibility" Value="Collapsed" />
<Setter TargetName="ContentSite" Property="Visibility" Value="Visible" />
<Setter Property="Text" Value=""/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I tried adding this event handler to remove the focus but it isn't working
private static void QuantityBox_IsMouseCapturedWithin(object sender, DependencyPropertyChangedEventArgs e)
{
var qBox = sender as ComboBox;
if (qBox.IsDropDownOpen == false)
{
Keyboard.ClearFocus();
flag = true;
}
}
Hope that this helps someone, the erratic behaviour was happening because I was using these triggers:
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter Property="IsDropDownOpen" Value="True"/>
<Setter TargetName="PART_EditableTextBox" Property="Visibility" Value="Visible" />
<Setter TargetName="ContentSite" Property="Visibility" Value="Collapsed" />
<Setter Property="IsEditable" Value="True"/>
</Trigger>
<Trigger Property="IsMouseCaptured" Value="False">
<Setter Property="IsDropDownOpen" Value="False"/>
<Setter TargetName="PART_EditableTextBox" Property="Visibility" Value="Collapsed" />
<Setter TargetName="ContentSite" Property="Visibility" Value="Visible" />
<Setter Property="Text" Value=""/>
</Trigger>
The triggers were ment to handle the visibility toggle between the TexBlock and the TextBox (showing the TextBlock when the ComboBox was inactive and the TextBox when it is focused so the user can type and filter).
So I removed the triggers and handled that behaviour in a dependency property:
public static readonly DependencyProperty MouseCapturedProperty = DependencyProperty.RegisterAttached("MouseCaptured",
typeof(bool), typeof(QuantitiesBoxBehaviours),
new UIPropertyMetadata(false, MouseCapturedPropertyChangedCallback));
public static bool GetMouseCaptured(UIElement element)
{
return (bool)element.GetValue(MouseCapturedProperty);
}
public static void SetMouseCaptured(UIElement element, bool command)
{
element.SetValue(MouseCapturedProperty, command);
}
private static void MouseCapturedPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var qBox = d as ComboBox;
bool value = GetMouseCaptured(qBox);
if (qBox != null && value)
{
qBox.IsMouseCaptureWithinChanged += QBox_IsMouseCaptureWithinChanged;
qBox.DropDownOpened += QBox_DropDownOpened;
}
}
private static void QBox_DropDownOpened(object sender, EventArgs e)
{
var qBox = sender as ComboBox;
var template = qBox.Template;
var txtBox = template.FindName("PART_EditableTextBox", qBox) as TextBox;
var txtBlock = template.FindName("ContentSite", qBox) as TextBlock;
txtBlock.Visibility = Visibility.Collapsed;
txtBox.Visibility = Visibility.Visible;
}
private static void QBox_IsMouseCaptureWithinChanged(object sender, DependencyPropertyChangedEventArgs e)
{
var qBox = sender as ComboBox;
var template = qBox.Template;
var txtBox = template.FindName("PART_EditableTextBox", qBox) as TextBox;
var txtBlock = template.FindName("ContentSite", qBox) as TextBlock;
if (qBox.IsDropDownOpen == false)
{
Keyboard.ClearFocus();
txtBox.Visibility = Visibility.Collapsed;
txtBlock.Visibility = Visibility.Visible;
qBox.ItemsSource = _presentationQuantities;
flag = true;
}
}
That solved the problem and now it's working great, that property was set to the ComboBox.
do you see anything wrong with this trigger?
<Border Margin="2" BorderBrush="#6593CF" BorderThickness="1.5" >
<Border.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding IsCreating, UpdateSourceTrigger=PropertyChanged}" Value="true">
<Setter Property="Border.BorderBrush" Value="Lime"/>
<Setter Property="Border.BorderThickness" Value="3" />
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
</Border>
It is bound to this property:
private bool _IsCreating = false;
public bool IsCreating
{
get
{
return _IsCreating;
}
set
{
if (_IsCreating == value)
{
return;
}
_IsCreating = value;
RaisePropertyChanged("IsCreating");
}
}
When I set IsCreating = true, the style does not update.
You have set BorderBrush and BorderThinkness inline on your border. Inline declaration has quite hight precedence and override your trigger. Remove your inline declaration from border and move it to trigger:
<Border Margin="2">
<Border.Style>
<Style TargetType="{x:Type Border}">
<Style.Triggers>
<DataTrigger
Binding="{Binding Path=DataContext.IsCreating, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
Value="true">
<Setter Property="BorderBrush" Value="Lime" />
<Setter Property="BorderThickness" Value="3" />
</DataTrigger>
<DataTrigger
Binding="{Binding Path=DataContext.IsCreating, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
Value="false">
<Setter Property="BorderBrush" Value="#6593CF" />
<Setter Property="BorderThickness" Value="1.5" />
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<CheckBox IsChecked="{Binding IsCreating}" />
</Border>
I have a datagrid binded to an object collection.
One property of the objects is a string that store a color value.
On this "COLORBACKGROUND" cell click, a colorpicker opens to change it.
What I need is to change the background color of the cell by the value displayed in datagrid rows (#RGB).
<DataGrid SelectionUnit="Cell" SelectedCellsChanged="DgDataTable_OnSelectedCellsChanged" x:Name="DgDataTable" Grid.Row="0" Grid.ColumnSpan="2" Margin="10,20,10,0" AutoGenerateColumns="true" HeadersVisibility="All" RowHeaderWidth="20" Style="{StaticResource AzureDataGrid}" GridLinesVisibility="Horizontal" LoadingRow="dgDataTable_LoadingRow" ColumnHeaderHeight="10" AlternatingRowBackground="{DynamicResource {x:Static SystemColors.GradientActiveCaptionBrushKey}}" AutoGeneratingColumn="DgDataTable_AutoGeneratingColumn">
<DataGrid.RowHeaderStyle>
<Style TargetType="DataGridRowHeader">
<Setter Property="FontSize" Value="10"/>
<Setter Property="Background" Value="LightCyan"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
</Style>
</DataGrid.RowHeaderStyle>
<DataGrid.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="TextBlock.TextAlignment" Value="Center"/>
<!-- <Style.Triggers>
<Trigger Property="Text" Value="John">
<Setter Property="Background" Value="LightGreen"/>
</Trigger>
</Style.Triggers> -->
</Style>
</DataGrid.CellStyle>
</DataGrid>
I tried something with AutoGenerating column :
private void DgDataTable_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
if (e.PropertyName == "SrcAlert")
{
DataGridComboBoxColumn cb = new DataGridComboBoxColumn();
e.Column = cb;
cb.ItemsSource = new List<string> {"1", "2"};
cb.SelectedValueBinding = new Binding("SrcAlert");
e.Column.Header = "SrcAlert";
}
if (e.PropertyName.Equals("ColorBackground"))
{
DataGridTextColumn tc = new DataGridTextColumn();
e.Column = tc;
tc.Foreground = (Color)ColorConverter.ConvertFromString(DgDataTable.CurrentCell.Item.ColorBackground);
}
}
this Item.ColorBackground doesn't compile... I put it for my explanation, thats what I need.
I tried another solution I found :
if (e.PropertyName.Equals("ColorBackground"))
{
string s = DgDataTable.CurrentCell.Item.ToString();
e.Column.CellStyle.Setters.Add(new Setter(DataGridCell.BackgroundProperty, (Color)ColorConverter.ConvertFromString(s)));
}
but that was a fail.
Thank you for your help !
Edit : A screenshot of ASh solution that works perfectly for me:
EDIT : I adapted your solution for multiple columns with color Picker :
I add style setters to display only colors in the cells :
<Style TargetType="DataGridCell" x:Key="ColorPickerCellBG"
BasedOn="{StaticResource CommonCell}">
<Setter Property="Background" Value="{Binding Path=BG}"/>
<Setter Property="Foreground" Value="Transparent"/>
<Setter Property="Width" Value="30"></Setter>
</Style>
<Style TargetType="DataGridCell" x:Key="ColorPickerCellAL"
BasedOn="{StaticResource CommonCell}">
<Setter Property="Background" Value="{Binding Path=AL}"/>
<Setter Property="Foreground" Value="Transparent"/>
<Setter Property="Width" Value="30"></Setter>
</Style>
<Style...
When the cell is clicked, the rgb color value is visible, the style must be "ClickedCell"...
How can I Improve that ?
it is possible to apply special style to a single auto-generated column.
declare two cell styles in resources
<Window.Resources>
<Style TargetType="DataGridCell" x:Key="CommonCell"
BasedOn="{StaticResource {x:Type DataGridCell}}">
<Setter Property="TextBlock.TextAlignment" Value="Center"/>
</Style>
<Style TargetType="DataGridCell" x:Key="ColorPickerCell"
BasedOn="{StaticResource CommonCell}">
<Setter Property="Background" Value="{Binding Path=ColorBackground}"/>
</Style>
</Window.Resources>
ColorPickerCell inherits CommonCell style.
<DataGrid SelectionUnit="Cell"
x:Name="DgDataTable"
AutoGenerateColumns="true" HeadersVisibility="All" RowHeaderWidth="20"
GridLinesVisibility="Horizontal"
ColumnHeaderHeight="10"
AlternatingRowBackground="{DynamicResource {x:Static SystemColors.GradientActiveCaptionBrushKey}}"
CellStyle="{StaticResource CommonCell}"
AutoGeneratingColumn="DgDataTable_AutoGeneratingColumn">
<DataGrid.RowHeaderStyle>
<Style TargetType="DataGridRowHeader">
<Setter Property="FontSize" Value="10"/>
<Setter Property="Background" Value="LightCyan"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
</Style>
</DataGrid.RowHeaderStyle>
</DataGrid>
change CellStyle for a generated column:
private void DgDataTable_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
if (e.PropertyName == "ColorBackground")
{
e.Column.CellStyle = (sender as DataGrid).FindResource("ColorPickerCell") as Style;
}
}
Apply a Converter, this Converter is used for two diff. purpose hence returns two diff types. Beauty of this approach is : You can change the property in XAML itself. No change needed in code now, and hence it is MVVM friendly.
For example, in DataTrigger change Value=BkgProp to Value=Name and see.
Sample XAML :
<Window ...>
<Window.Resources>
<local:PropBasedStringToColorConverter x:Key="StringToColorCnvKey"/>
</Window.Resources>
<Grid>
<DataGrid x:Name="Dgrd">
<DataGrid.Resources>
<Style TargetType="DataGridCell">
<Style.Triggers>
<DataTrigger Binding="{Binding .Column, RelativeSource={RelativeSource Self}, Converter={StaticResource StringToColorCnvKey}}" Value="BkgProp">
<Setter Property="Background" Value="{Binding BkgProp, Converter={StaticResource StringToColorCnvKey}}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.Resources>
</DataGrid>
</Grid>
</Window>
Sample Data :
Dgrd.ItemsSource = new[] { new { BkgProp = "#abcdef", Name = "Anjum" }, new { BkgProp = "#edf2ed", Name = "Anjum" }, new { BkgProp = "#ff0000", Name = "Anjum" } }.ToList();
Converter Code :
public class PropBasedStringToColorConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
object result = null;
if (value == null) return "N/A";
if (value.GetType() == typeof(DataGridTextColumn))
{
string path = ((Binding)((DataGridTextColumn)value).Binding).Path.Path;
return path;
}
else if (value.GetType() == typeof(string))
{
result = new SolidColorBrush((Color)ColorConverter.ConvertFromString(value.ToString()));
}
return result;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}