I have a very basic WPF application with a MS SQL server as data source attached to it. My datagrid is declared as follows:
<DataGrid HorizontalAlignment="Left" Margin="10,88,0,0" VerticalAlignment="Top" Height="456" Width="1018" ItemsSource="{Binding}" />
When I run the app I see the data loaded into the grid from the database, but the column captions look odd. Every caption that originally contains an underscore has this underscore removed: some_title turns to sometitle.
I found out that's because the underscore is recognized as a control symbol to turn the next symbol into a mnemonic.
How can I disable this behavior?
I found out this behavior can be bypassed if you double the single underscores, i.e. some__title instead of some_title. But since my data source is an external database I can't influence that. Or maybe with a converter?
I figured the best approach would be to turn the property RecognizesAccessKey to false, but unfortunately it somehow isn't accessible.
I'm new to WPF, thanks for your help!
P.S. Her is a picture of Snoop (if that helps)
edit: my target framework is .net 4.5
Even though this is an old question, I came through solution. It might help someone.
<DataGrid HorizontalAlignment="Left" Margin="10,88,0,0" VerticalAlignment="Top" Height="456" Width="1018" ItemsSource="{Binding}" >
<DataGrid.ColumnHeaderStyle>
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="DataGridColumnHeader">
<Border>
<ContentPresenter
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
RecognizesAccessKey="False" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</DataGrid.ColumnHeaderStyle>
</DataGrid>
The best solution I could come up with is intercepting the DataGrid event AutoGeneratingColumn and replace all underscores with two underscores like this:
private void DataGrid_AutoGeneratingColumn_1(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
string header = e.Column.Header.ToString();
// Replace all underscores with two underscores, to prevent AccessKey handling
e.Column.Header = header.Replace("_", "__");
}
In my understanding it is (sadly) not possible to override the value of RecognizesAccessKey of the underlying ContentPresenter without redefining the whole control template.
See this thread on the msdn forums: How to set RecognizesAccessKey on labels without influencing other parameters?.
You can use custom columns , when you use custom column then you can define columns caption as you need.
To add to the accepted answer, if you want to keep the original style of datagrid do as seen below and change the ContentPresenter's RecognizeAccessKey to False.
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridColumnHeader}">
<Grid>
<Themes:DataGridHeaderBorder BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" IsClickable="{TemplateBinding CanUserSort}" IsPressed="{TemplateBinding IsPressed}" IsHovered="{TemplateBinding IsMouseOver}" Padding="{TemplateBinding Padding}" SortDirection="{TemplateBinding SortDirection}" SeparatorBrush="{TemplateBinding SeparatorBrush}" SeparatorVisibility="{TemplateBinding SeparatorVisibility}">
<ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" RecognizesAccessKey="False" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Themes:DataGridHeaderBorder>
<Thumb x:Name="PART_LeftHeaderGripper" HorizontalAlignment="Left">
<Thumb.Style>
<Style TargetType="{x:Type Thumb}">
<Setter Property="Width" Value="8"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Cursor" Value="SizeWE"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Thumb}">
<Border Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Thumb.Style>
</Thumb>
<Thumb x:Name="PART_RightHeaderGripper" HorizontalAlignment="Right">
<Thumb.Style>
<Style TargetType="{x:Type Thumb}">
<Setter Property="Width" Value="8"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Cursor" Value="SizeWE"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Thumb}">
<Border Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Thumb.Style>
</Thumb>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Related
var item = new RadioButton { Content = "some_name"};
item.Checked += radioButtonClick;
item.Unchecked += radioButtonUnClick;
actual display is somename. Underscore is missing. To fix this used the following style on the radio button, but it has side effects. Radiobutton icon is not visible.
<Style x:Key="{x:Type RadioButton}" TargetType="{x:Type RadioButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type RadioButton}">
<Border Background="{TemplateBinding Background}"
BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}"
Padding="{TemplateBinding Padding}"
SnapsToDevicePixels="true">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
RecognizesAccessKey="False"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Thanks in advance
To display underscore in radiobutton please use below code.
<RadioButton ...... >
<TextBlock Text="SELECT_ME" />
</RadioButton>
For code behind
var item = new RadioButton { Content = new TextBlock { Text = "SELECT_ME" } };
Use double underscores, since a single underscore followed by a letter is interpreted as the definition of an access key. Access keys appear underlined when you press the Alt key.
If you want "some_name" to appear on your label/checkbox/button/.. you need to specify the content as "some__name".
You can read more about access keys in https://learn.microsoft.com/en-us/dotnet/framework/wpf/controls/how-to-create-a-control-that-has-an-access-key-and-text-wrapping
I'm creating a custom control which is based on a ToggleButton.
With this simple style in Generic.xaml I can't get the default togglebutton styles working on my custom control.
I'm setting the foreground, background and borderbrush to the systemcolors, but nothing happens.
<Style TargetType="{x:Type local:PopupButton}" BasedOn="{StaticResource {x:Type ToggleButton}}">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" />
<Setter Property="BorderBrush" Value="{DynamicResource {x:Static SystemColors.ActiveBorderBrushKey}}" />
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="MinHeight" Value="22" />
<Setter Property="MinWidth" Value="75" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:PopupButton}">
<Grid SnapsToDevicePixels="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ToggleButton Grid.Column="0">
<ToggleButton.Template>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
RecognizesAccessKey="True" />
</ControlTemplate>
</ToggleButton.Template>
<ContentPresenter Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Margin="{TemplateBinding Margin}"
RecognizesAccessKey="true" />
</ToggleButton>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I've overridden the defaultstylekey:
public class PopupButton : ToggleButton
{
static PopupButton()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(PopupButton), new FrameworkPropertyMetadata(typeof(PopupButton)));
}
// ...
Been testing, playing around with other (xaml) code but after a few hours I still have not figured out why the default style is not applied.
In your ControlTemplate for local:PopupButton you have a toggle button but you are overring it's template as well. Try removing:
<ToggleButton.Template>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
RecognizesAccessKey="True" />
</ControlTemplate>
</ToggleButton.Template>
I am making a wpf form(moved from winform a couple days ago), and i wanted to customize my textbox. I got the textbox to behave how i want it to, but now i cant give it input, and it does not respond at all when i click it. I think i broke it, anyways here is my code:
<TextBox x:Name="textBox" HorizontalAlignment="Left" Height="23" Margin="10,48,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="120" Foreground="White">
<TextBox.Style>
<Style TargetType="{x:Type TextBox}">
<Setter Property="BorderBrush" Value="#FF497AB4"/>
<Setter Property="Background" Value="#FF2E2E2E"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="BorderBrush" Value="OrangeRed"/>
</Trigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
So what am i doing wrong? Thanks!
Try adding a Scrollviewer to your template, like this:
<Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
<ScrollViewer Margin="0" x:Name="PART_ContentHost"/>
</Border>
You've got some example templates here
The problem was that the template didn't have a ContentHost, so it would not render the contents. To add a ContentHost, you should add an element named "PART_ContentHost" as explained here
I'm using following code to get the cells of my datagrid to display text in the center:
<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}">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
<ContentPresenter VerticalAlignment="Center" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="VerticalAlignment" Value="Stretch"/>
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="Foreground" Value="Black">
</Setter>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFE3ECF7" Offset="0"/>
<GradientStop Color="#FF71DDF9" Offset="1"/>
<GradientStop Color="#FF5091DC" Offset="0.546"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<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>
</Style.Triggers>
</Style>
it works fine, except that when I'm editing the contents of a cell, it looks like this:
I can resize the textBox by using the setter:
<Trigger Property="IsEditing" Value="True">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridCell}">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
<ContentPresenter VerticalAlignment="Stretch" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
but this causes the text in the textbox to move up:
How do I make the textbox to take the whole cell without moving the text as well?
UPDATE When I use following template:
<ControlTemplate TargetType="{x:Type DataGridCell}">
<Grid VerticalAlignment="Center">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
<ContentPresenter VerticalAlignment="Stretch" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Border>
</Grid>
</ControlTemplate>
My grid selection gets scruwed up:
will putting it in the grid that is stretched work? Although that would add an additional control for each cell..
<ControlTemplate TargetType="{x:Type DataGridCell}">
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="White">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
<ContentPresenter VerticalAlignment="Center" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Border>
</Grid>
</ControlTemplate>
also, thanks to the screenshot, there it looks like that DataGrid's SelectionUnit is a Row, is that needed for your app? If it's not, then specifying SelectionUnit="Cell" and forcing active selection's color to be white, also will solve the problem
I have managed to get further with my read only check box after a bit of a break and now have the functionality I want in a reasonably elegant form. The problem is I have used a bit of a hack to make it work, although this is not a disaster it would be nice to do it better.
To recap: I want a regular looking checkbox that does not self check when it is clicked, instead the click event triggers a background worker that later on causes a variable to be updated. This variable is bound to checkbox.ischecked and it is then updated with the new value.
I would like to use a control template based on the idea here:
A read-only CheckBox in C# WPF
I have modified this and stripped out stuff I thought I didn't need (perhaps unwisely) and ended up with:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero">
<!-- -->
<Style x:Key="ReadOnlyCheckBoxStyle" TargetType="{x:Type CheckBox}" >
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type CheckBox}">
<BulletDecorator SnapsToDevicePixels="true" Background="Transparent">
<BulletDecorator.Bullet>
<Microsoft_Windows_Themes:BulletChrome Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
RenderMouseOver="{TemplateBinding IsMouseOver}"
IsChecked="{TemplateBinding Tag}">
</Microsoft_Windows_Themes:BulletChrome>
</BulletDecorator.Bullet>
<ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Margin="{TemplateBinding Padding}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
RecognizesAccessKey="True" />
</BulletDecorator>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{StaticResource {x:Static SystemColors.GrayTextBrushKey}}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
This checkbox works as described above and I call it like this:
<CheckBox x:Name="uiComboBox" Content="Does not set the backing property, but responds to it."
Style="{StaticResource ReadOnlyCheckBoxStyle}" Tag="{Binding MyBoolean}" Click="uiComboBox_Click"/>
The hack I made was to use the 'Tag' DependencyProperty to carry the data binding into the control template. This bypasses whatever mechanism is normally causing the checkbox to self check. To revert to a normal acting checkbox just change binding to Tag to a binding to IsChecked and inside the BulletDecorator set the TemplateBinding to IsChecked instead of Tag.
So I guess my questions are:
Have I got the wrong end of the stick? Is there a place where I can override whatever mechanism causes the box to self check? Perhaps in ControlTemplate Triggers?
Is it a good idea to go around eliminating any spare XAML that I think is just being brought in from the default CheckBox or should I try and keep a complete replacement for all styles?
If what I am doing is not too crazy, can I add a dependency property in XAML so that I don't have to use the Tag property?
It also occurs to me that perhaps what I really want is a button control that looks like a checkbox, maybe an invisible button with the usual animated checkbox on top which I bind data to the graphic of. Any thoughts on that plan would also be very welcome.
Thanks very much
Ed
I managed to sort out this problem and my ReadOnlyCheckBox idea, in the end I created a custom control based around Button and then applied a style to make it look like a CheckBox. I added my own IsChecked property that does not get set when the user clicks but is bound to the data so the displayed check only appears when the data changes.
C#:
public class ReadOnlyCheckBoxControl : System.Windows.Controls.Button
{
public static DependencyProperty IsCheckedProperty;
public ReadOnlyCheckBoxControl()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(ReadOnlyCheckBoxControl), new FrameworkPropertyMetadata(typeof(ReadOnlyCheckBoxControl)));
}
public bool IsChecked
{
get { return (bool)GetValue(IsCheckedProperty); }
set { SetValue(IsCheckedProperty, value); }
}
static ReadOnlyCheckBoxControl()
{
IsCheckedProperty = DependencyProperty.Register("IsChecked", typeof(bool), typeof(ReadOnlyCheckBoxControl));
}
}
XAML:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:y="clr-namespace:ReadOnlyCheckBoxControlNS;assembly="
xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero">
<SolidColorBrush x:Key="CheckBoxFillNormal" Color="#F4F4F4" />
<SolidColorBrush x:Key="CheckBoxStroke" Color="#8E8F8F" />
<Style x:Key="EmptyCheckBoxFocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Rectangle SnapsToDevicePixels="true"
Margin="1"
Stroke="Black"
StrokeDashArray="1 2"
StrokeThickness="1" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="CheckRadioFocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Rectangle SnapsToDevicePixels="true"
Margin="14,0,0,0"
Stroke="Black"
StrokeDashArray="1 2"
StrokeThickness="1" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type y:ReadOnlyCheckBoxControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type y:ReadOnlyCheckBoxControl}">
<BulletDecorator SnapsToDevicePixels="true" Background="Transparent">
<BulletDecorator.Bullet>
<Microsoft_Windows_Themes:BulletChrome Background="{StaticResource CheckBoxFillNormal}"
BorderBrush="{StaticResource CheckBoxStroke}"
RenderMouseOver="{TemplateBinding IsMouseOver}"
IsChecked="{TemplateBinding IsChecked}">
</Microsoft_Windows_Themes:BulletChrome>
</BulletDecorator.Bullet>
<ContentPresenter SnapsToDevicePixels="True"
HorizontalAlignment="Left"
Margin="4,0,0,0"
VerticalAlignment="Center"
RecognizesAccessKey="True" />
</BulletDecorator>
<ControlTemplate.Triggers>
<Trigger Property="HasContent" Value="true">
<Setter Property="FocusVisualStyle" Value="{StaticResource CheckRadioFocusVisual}" />
<Setter Property="Padding" Value="4,0,0,0" />
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{StaticResource {x:Static SystemColors.GrayTextBrushKey}}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>