I've got DataGrid with several DataGridTextColumn's, one of which is editable.
I need to intercept TextChanged event for the cell that is being edited.
I've tried editing style and adding
<EventSetter Event="TextChanged" Handler="TaskDescription_TextChanged"/>
but I'm getting
Cannot find the Style Event 'TextChanged' on the type 'System.Windows.Controls.DataGridCell'
Is there an easy way to get notified of the text change in DataGridTextColumn except by Two-Way binding?
Here's the XAML code:
<Style x:Key="CenteredTextColumn" TargetType="{x:Type DataGridCell}">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridCell}">
<Grid Height="30">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
<ContentPresenter VerticalAlignment="Center" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="VerticalAlignment" Value="Stretch"/>
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="Foreground" Value="Black"/>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="{StaticResource SelectedCellBackground}"/>
<Setter Property="Foreground" Value="White"/>
<!--<Setter Property="BorderBrush" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>-->
</Trigger>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<!--<Setter Property="BorderBrush" Value="{DynamicResource {x:Static DataGrid.FocusBorderBrushKey}}"/>-->
</Trigger>
<Trigger Property="IsEditing" Value="True">
<Setter Property="Background" Value="Transparent"/>
</Trigger>
</Style.Triggers>
</Style>
and the EventSetter:
<Style x:Key="ProjectInfoEditeableCell" TargetType="{x:Type DataGridCell}" BasedOn="{StaticResource CenteredTextColumn}">
<EventSetter Event="TextChanged" Handler="TaskDescription_TextChanged"/>
</Style>
Related
This question already has an answer here:
DataGrid row selection not working when padding is added to cells
(1 answer)
Closed 4 years ago.
I'm building a Datagrid that has rows with height=40. On a row selection, the program opens a new tab with a User Control specific to that item.
When I click anywhere in the row that's outside of the cell contents (Red boxes in this image), The event fires but 'CurrentItem' does not get updated.
Essentially, the row only gets selected if the cell contents are clicked. Has anyone else dealt with this, and have a solution for what's going on?
Here's my styling:
<DataGrid Name="MachinesGrid" ItemsSource="{Binding MainData.Machines}">
<DataGrid.Style>
<Style TargetType="DataGrid">
<Setter Property="SelectionMode" Value="Single" />
<Setter Property="SelectionUnit" Value="FullRow" />
<Setter Property="AutoGenerateColumns" Value="False" />
<Setter Property="ColumnWidth" Value="Auto" />
<Setter Property="CanUserAddRows" Value="False" />
<Setter Property="Background" Value="{StaticResource BrushBackground}" />
<Setter Property="RowBackground" Value="{StaticResource BrushGreyMid}" />
<Setter Property="AlternatingRowBackground" Value="{StaticResource BrushGreyDark}" />
<Setter Property="GridLinesVisibility" Value="None" />
<Setter Property="ColumnHeaderStyle">
<Setter.Value>
<Style TargetType="DataGridColumnHeader">
<Setter Property="Background" Value="{StaticResource BrushBlue}" />
<Setter Property="Foreground" Value="{StaticResource BrushWhite}" />
<Setter Property="Height" Value="40" />
<Setter Property="FontWeight" Value="SemiBold" />
</Style>
</Setter.Value>
</Setter>
<Setter Property="CellStyle">
<Setter.Value>
<Style TargetType="DataGridCell">
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Foreground" Value="{StaticResource BrushWhite}" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
</Style>
</Setter.Value>
</Setter>
<Setter Property="RowStyle">
<Setter.Value>
<Style TargetType="DataGridRow">
<Setter Property="Height" Value="40" />
<EventSetter Event="MouseLeftButtonUp" Handler="EventSetter_OnHandler" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{StaticResource BrushGreyLite}" />
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="{StaticResource BrushBlue}" />
</Trigger>
</Style.Triggers>
</Style>
</Setter.Value>
</Setter>
</Style>
</DataGrid.Style>
As far as I know your problem is that selection is initially triggered in DataGridCell, by setting
<Setter Property="VerticalAlignment" Value="Center" />
your are telling that DataGridCell should vertically centered within a DataGridRow which leads to some space top and bottom which is not part of the DataGridCell and therefore not triggering any selection.
To solve this you have to set VerticalAlignment to Stretch(default) but then your content isn't centered anymore, for this you have to override the ControlTemplate of DataGridCell:
<ControlTemplate TargetType="{x:Type DataGridCell}">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
<ContentPresenter VerticalAlignment="{TemplateBinding VerticalContentAlignment}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Border>
</ControlTemplate>
Now you can set VerticalContentAlignment and HorizontalContentAlignment on DataGridCell to align your content.
Your DataGridCell-Style should then look like this
<Style TargetType="DataGridCell">
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="Foreground" Value="{StaticResource BrushWhite}" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridCell}">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
<ContentPresenter VerticalAlignment="{TemplateBinding VerticalContentAlignment}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I have a custom 3 state Button that is supposed to cycle between 3 different states (colours) as it is clicked. However the click handler I've written doesn't have any effect on the background colour of the Border within the ControlTemplate.
I'm probably missing something very simple, but I'd really appreciate a fresh pair of eyes to spot what it may be.
The ControlTemplate and Button.Click handler are below:
<Style x:Key="FilterButtonStyle" TargetType="{x:Type local:FilterButton}"
BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="ButtonBackground" BorderThickness="0" Padding="0"
Margin="0" CornerRadius="6"
Background="{StaticResource blueShader}" >
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Effect" Value="{StaticResource glowShadow}">
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Foreground" Value="{StaticResource textBrush}"/>
<Setter Property="Margin" Value="4,4,0,4"></Setter>
<Setter Property="Padding" Value="4"></Setter>
<Setter Property="Height" Value="55"></Setter>
<Setter Property="Width" Value="55"></Setter>
<Setter Property="FontSize" Value="10"/>
<Setter Property="FontWeight" Value="Normal"/>
<Setter Property="TextBlock.TextWrapping" Value="Wrap"></Setter>
<Setter Property="HasDisabledState" Value="True"></Setter>
<Setter Property="OnColour" Value="{StaticResource greenShader}"></Setter>
<Setter Property="OffColour" Value="{StaticResource blueShader}"></Setter>
<Setter Property="DisabledColour" Value="{StaticResource redShader}"></Setter>
</Style>
private void FilterButton_Click(object sender, RoutedEventArgs e)
{
if (!this.CanChangeState) { return; }
// Get child border element.
Border border = this.Template.LoadContent() as Border;
// Cycle through button states.
switch (this.ButtonState)
{
case ButtonStates.Off:
this.ButtonState = ButtonStates.On;
border.Background = this.OnColour;
break;
case ButtonStates.On:
if (this.HasDisabledState)
{
this.ButtonState = ButtonStates.Disabled;
border.Background = this.DisabledColour;
}
else
{
this.ButtonState = ButtonStates.Off;
border.Background = this.OffColour;
}
break;
case ButtonStates.Disabled:
this.ButtonState = ButtonStates.Off;
border.Background = this.OffColour;
break;
}
}
Never mind, I found that a better way of handling this was to use ControlTemplate triggers to change the Button colour based on the ButtonState property.
<Style x:Key="FilterButtonStyle" TargetType="{x:Type local:FilterButton}"
BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="ButtonBackground" BorderThickness="0" Padding="0" Margin="0" CornerRadius="6"
Background="{StaticResource blueShader}" >
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Effect" Value="{StaticResource glowShadow}">
</Setter>
</Trigger>
<Trigger Property="local:FilterButton.ButtonState" Value="On">
<Setter TargetName="ButtonBackground" Property="Background" Value="{StaticResource greenShader}"></Setter>
</Trigger>
<Trigger Property="local:FilterButton.ButtonState" Value="Off">
<Setter TargetName="ButtonBackground" Property="Background" Value="{StaticResource blueShader}"></Setter>
</Trigger>
<Trigger Property="local:FilterButton.ButtonState" Value="Disabled">
<Setter TargetName="ButtonBackground" Property="Background" Value="{StaticResource redShader}"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Foreground" Value="{StaticResource textBrush}"/>
<Setter Property="Margin" Value="4,4,0,4"></Setter>
<Setter Property="Padding" Value="4"></Setter>
<Setter Property="Height" Value="55"></Setter>
<Setter Property="Width" Value="55"></Setter>
<Setter Property="FontSize" Value="10"/>
<Setter Property="FontWeight" Value="Normal"/>
<Setter Property="TextBlock.TextWrapping" Value="Wrap"></Setter>
<Setter Property="HasDisabledState" Value="True"></Setter>
</Style>
I am looking for something to set the BorderBrush Color of a Button inside my Mahapps Metro Window when i tabbing with my Keyboard, but I cannot find something. Is there a way to set a new color for the border?
You can create a style that overrides the default template, you can replace the colors with whatever you like and add more triggers if desired:
<Style TargetType="Button" x:Key="DefaultButtonStyle">
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="Background" Value="#3a3a3a"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="metro:ButtonHelper.PreserveTextCase" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}"
Margin="{TemplateBinding Margin}">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#424242"/>
</Trigger>
</Style.Triggers>
</Style>
Alright, so i made it with Aleksandr Albert answer. All i missed was the property IsFocused
<Style x:Key="ButtonMentorPlusStyle" TargetType="{x:Type Button}" BasedOn="{StaticResource AccentedSquareButtonStyle}">
<Setter Property="Foreground" Value="White" />
<Setter Property="Background" Value="#0D6373" />
<Setter Property="FontSize" Value="14" />
<Setter Property="FontFamily" Value="Arial" />
<Setter Property="FontStyle" Value="Normal" />
<Setter Property="MinWidth" Value="100" />
<Setter Property="MinHeight" Value="28" />
<Setter Property="Controls:ButtonHelper.PreserveTextCase" Value="True" />
<Setter Property="Padding" Value="10, 0, 10, 0" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Style.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="BorderBrush" Value="White" />
</Trigger>
</Style.Triggers>
</Style>
Thank you guys
I've found and tried many solutions on the internet which should allow me to disable the hover effect of my WPF ListBox but none of them seemed to work for me. This screenshot shows the hover effect I'd like to hide or get rid of:
This is (a simplified version) of the XAML code I currently have:
<ListBox ItemsSource="{Binding Logs}" Grid.Column="1" Width="800" Height="100" >
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Style.Triggers>
<Trigger Property="Control.IsMouseOver" Value="True">
<Setter Property="Control.Background" Value="Transparent" />
</Trigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
However, it doesn't seem to work for me for a reason or another. Could my parent ListBox (the one in the background) or another control override it's child's style by any chance? (I already tried to override the parents style as well)
Modify the default style of a ListBoxItem
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
<Setter Property="VerticalContentAlignment" Value="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
<Setter Property="Padding" Value="2,0,0,0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/>
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="true"/>
<Condition Property="Selector.IsSelectionActive" Value="false"/>
</MultiTrigger.Conditions>
<Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightBrushKey}}"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightTextBrushKey}}"/>
</MultiTrigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Just add a trigger
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Transparent"/>
</Trigger>
Getting rid of the blue devil?
If you have no need to click on your items the following will make it disappear, the highlighting on mouse hover:
<ListBox IsHitTestVisible="False">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="IsTabStop" Value="False" />
</Style>
</ListBox.ItemContainerStyle>
<ListBoxItem Content="Glad that" />
<ListBoxItem Content="they are over" />
<ListBoxItem Content="the days of the blue devil" />
</ListBox>
I've created template for combobox but it has strange view, data is not displaying:
Here is XAML code:
<Style TargetType="{x:Type ComboBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ComboBox}">
<Border Background="{TemplateBinding Background}" x:Name="Bd" BorderBrush="Gray" BorderThickness="2" CornerRadius="2">
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" TargetName="Bd"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
<Trigger Property="IsFocused" Value="true">
<Setter Property="BorderBrush" Value="Blue" TargetName="Bd"/>
<Setter Property="BorderThickness" Value="2"/>
</Trigger>
<Trigger Property="IsFocused" Value="false">
<Setter Property="BorderBrush" Value="Gray" TargetName="Bd"/>
<Setter Property="BorderThickness" Value="2"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
What i missed here?
Your template creates near to nothing which makes the default one work, i.e. there is no items popup, and there is no ContentPresenter for the selected item either. Have a look at the default template and you will see exactly what you are missing (Here is a question explaining where to get them).