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
Related
Here is a button which I styled, but I realized that there is no way for someone who uses the application to notice when button is mouse over / selected or something like that?
I just want some kind of notification when button is selected or whatever?
Any kind of solution will be acceptable for me so in case button is mouse hovered, or in case button is selected to notice user
that is that button!
Here is my current button:
<Button x:Name="btnOk"
SnapsToDevicePixels="True"
UseLayoutRounding="True"
IsDefault="True"
Grid.Row="2"
Grid.Column="1"
FontSize="15"
Width="140"
BorderThickness="1"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
Foreground="#0091EA"
Background="White"
Content="Ok!"
BorderBrush="#0091EA" Margin="5,10,0,10" HorizontalAlignment="Left" Click="btnPotvrdi_Click">
<Button.Style>
<Style TargetType="{x:Type Button}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="BlueViolet"/>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
<Button.Template>
<ControlTemplate TargetType="{x:Type Button}">
<Border BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}"
Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</Border>
</ControlTemplate>
</Button.Template>
</Button>
Specify the default background (White) in the Style and your trigger will work as expected:
<Button x:Name="btnOk"
SnapsToDevicePixels="True"
UseLayoutRounding="True"
IsDefault="True"
Grid.Row="2"
Grid.Column="1"
FontSize="15"
Width="140"
BorderThickness="1"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
Foreground="#0091EA"
Content="Ok!"
BorderBrush="#0091EA" Margin="5,10,0,10" HorizontalAlignment="Left" Click="btnPotvrdi_Click">
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="White" />
<Style.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="Background" Value="Green"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="BlueViolet"/>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
<Button.Template>
<ControlTemplate TargetType="{x:Type Button}">
<Border BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}"
Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</Border>
</ControlTemplate>
</Button.Template>
</Button>
A "local" value takes precedence over a value set by a Setter in a Style: https://msdn.microsoft.com/en-us/library/ms743230(v=vs.110).aspx
I have a small problem in my wpf application. I have two classes GameObject and Block. Both are CustomControls, GameObject derives directly from Control and Block derives from GameObject. I want to write a style to block which will be based on the GameObject style. Here is a piece of code
<Style TargetType="{x:Type primitives:GameObject}" x:Key="game">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type primitives:GameObject}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Grid.Row" Value="{Binding Path=Row, RelativeSource={RelativeSource Self}}"/>
<Setter Property="Grid.Column" Value="{Binding Path=Column, RelativeSource={RelativeSource Self}}"/>
</Style>
<Style TargetType="{x:Type primitives:Block}" BasedOn="{StaticResource game}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type primitives:Block}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
However, if I added a x:Key to the first style, it wouldn't be automatically applied to every instance of GameObject, so my Style is useless in other files in program. Any ideas what to do?
You can still apply it to both all and specific, you just need a global style that referances it.
<Style TargetType="{x:Type primitives:GameObject}" x:Key="game">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type primitives:GameObject}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Grid.Row" Value="{Binding Path=Row, RelativeSource={RelativeSource Self}}"/>
<Setter Property="Grid.Column" Value="{Binding Path=Column, RelativeSource={RelativeSource Self}}"/>
</Style>
<Style TargetType="{x:Type primitives:Block}" BasedOn="{StaticResource game}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type primitives:Block}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type primitives:GameObject}" BasedOn="{StaticResource game}">
</Style>
BasedOn has some definite possibilities if you need to apply a named style within a scope (object.resources) or globally.
I have a button that has two images attached to its DataContext.
The displayed image is bind to the button IsEnabled property.
Here is the XAML for the button:
<Button Name="SubmitButton" IsEnabled="{Binding IsSubmitEnabled}" Background="Transparent">
<Image Name="SubmitButtonImage" Height="50" Width="291" MinHeight="50" MinWidth="291">
<Image.Style>
<Style TargetType="{x:Type Image}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsSubmitEnabled}" Value="True">
<Setter Property="Source" Value="/Resources/startup/Submit_enabled.png"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding IsSubmitEnabled}" Value="False">
<Setter Property="Source" Value="/Resources/startup/Submit_disabled.png"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
Now instead of specifying the image in DataTrigger Value I want to use a template that is defined in the file like this:
<ControlTemplate x:Key="SubmitEnabledTemplate" TargetType="{x:Type Button}">
<Border
Height="{TemplateBinding Height}"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
SnapsToDevicePixels="true">
<Image Source="/Resources/startup/Submit_enabled.png"></Image>
</Border>
</ControlTemplate>
<ControlTemplate x:Key="SubmitDisabledTemplate" TargetType="{x:Type Button}">
<Border
Height="{TemplateBinding Height}"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
SnapsToDevicePixels="true">
<Image Source="/Resources/startup/Submit_disabled.png"></Image>
</Border>
</ControlTemplate>
Any ideas how to do that?
Try a DataTemplate Trigger, here is an example which may be relevant:
<ItemsControl ItemsSource="{Binding Path=Groups}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<ContentControl x:Name="cc" Content="{Binding}" ContentTemplate="{DynamicResource ItemTemplate}"/>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Path=IsLeaf}" Value="False">
<Setter TargetName="cc" Property="ContentTemplate" Value="{DynamicResource GroupTemplate}"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
See DataTemplate.Triggers property.
WPF has option to switch control template also
CODE:
<Window.Resources>
<ControlTemplate x:Key="SubmitEnabledTemplate" TargetType="{x:Type Button}">
<Border
Height="{TemplateBinding Height}"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
SnapsToDevicePixels="true">
<Image Source="/Resources/startup/Submit_enabled.png"></Image>
</Border>
</ControlTemplate>
<ControlTemplate x:Key="SubmitDisabledTemplate" TargetType="{x:Type Button}">
<Border
Height="{TemplateBinding Height}"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
SnapsToDevicePixels="true">
<Image Source="/Resources/startup/Submit_disabled.png"></Image>
</Border>
</ControlTemplate>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="50" />
</Grid.RowDefinitions>
<Button Grid.Row="0">
<Button.Style>
<Style TargetType="Button">
<Setter Property="Template"
Value="{StaticResource SubmitEnabledTemplate}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsSubmitButtonEnabled}"
Value="False">
<Setter Property="Template"
Value="{StaticResource SubmitDisabledTemplate}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</Grid>
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>
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