I have a control template for a Thumb defined in a Resource Dictionary.
<ControlTemplate TargetType="{x:Type Thumb}">
<Border x:Name="PART_Border"
Cursor="SizeWE"
Padding="{TemplateBinding Padding}"
Background="{TemplateBinding Background}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</ControlTemplate>
The ControlTemplate is implemented in a style I call GridColumnHeaderGripper and this style is implemented in another Resource Dictionary
<ControlTemplate TargetType="GridViewColumnHeader">
<DockPanel>
<Thumb x:Name="PART_HeaderGripper"
DockPanel.Dock="Right"
Margin="0,0,-8,0"
Cursor="SizeWE"
Style="{StaticResource GridColumnHeaderGripper}" />
etc...
It works great, however, when I begin dragging the Thumb, then the cursor changes from "SizeWE" to "None". I saw another post similar to this on StackOverflow that suggested a Trigger to set the Cursor.
<ControlTemplate.Triggers>
<Trigger Property="IsDragging" Value="True">
<Setter Property="Cursor" Value="SizeWE"/>
</Trigger>
</ControlTemplate.Triggers>
However this solution didn't work for me.
From what I can understand is that we can override the cursor using the Mouse.OverrideCursor static property. Is it possible to set this static property using a Trigger? Is there anything I can do to change the cursor when dragging a thumb?
Add 'Cursor' attribute where you actually declare thumb.
<Window x:Class="ThumbCursor.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ThumbCursor"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<ControlTemplate x:Key="template" TargetType="{x:Type Thumb}">
<Border x:Name="PART_Border"
Cursor="SizeWE"
Padding="{TemplateBinding Padding}"
Background="{TemplateBinding Background}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</ControlTemplate>
</Window.Resources>
<Grid>
<Thumb x:Name="thmb" Height="50" Width="100" Cursor="SizeWE" Template="{StaticResource template}" DragDelta="thmb_DragDelta"/>
</Grid>
</Window>
Related
I want a ControlTemplate for a few buttons so I can control the colour of the button when the mouse is over it. The problem is that I use a border as the ControlTemplate content and I want the size (BorderThickness) of that border to be equal to the button's size. And since the button is part of a grid, its size is flexible. This is my code so far:
<Window x:Class="WPFTesting.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WPFTesting"
mc:Ignorable="d"
Title="MainWindow" Height="400" Width="350">
<Window.Resources>
<Style TargetType="Button" x:Key="ex">
<Setter Property="Background" Value="Black"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="FontSize" Value="50"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border BorderBrush="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Button Content="Btn0" Margin="0, 10, 0, 30" Style="{StaticResource ex}" Grid.Row="0"/>
<Button Content="Btn1" Margin="0, 10, 0, 30" Grid.Row="1"/>
<Button Content="Btn2" Margin="0, 10, 0, 30" Grid.Row="2"/>
</Grid>
How can I make the BorderThickness fill the entire grid row. Should I even be using a border as the ControlTemplate content in the first place?
You should just write
<ControlTemplate TargetType="Button">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}">
<ContentPresenter
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
</ControlTemplate>
I've configured ListBox to use custom ControlTemplate for it self and custom ControlTemplate for ListBoxItem. Unfortunately such change disables the default behvaiour of DisplayMemberPath property.
// resource dictionary of ListBox control template
<ControlTemplate x:Key="CustomListBox" TargetType="ListBox" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:s="clr-namespace:System;assembly=mscorlib">
<Border CornerRadius="3" BorderThickness="{TemplateBinding Border.BorderThickness}" Padding="1,1,1,1" BorderBrush="{TemplateBinding Border.BorderBrush}" Background="{TemplateBinding Panel.Background}" Name="Bd" SnapsToDevicePixels="True">
<ScrollViewer Padding="{TemplateBinding Control.Padding}" Focusable="False">
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
</ScrollViewer>
</Border>
</ControlTemplate>
//trigger code omitted
<Style TargetType="ListBox">
<Setter Property="Control.Template" Value="{StaticResource CustomListBox}"></Setter>
</Style>
// resource dictionary of ListBoxItem control template
<ControlTemplate x:Key="CustomListBoxItem" TargetType="ListBoxItem" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel>
<Border BorderThickness="0" CornerRadius="3" Padding="6 6" BorderBrush="{TemplateBinding Border.BorderBrush}" Background="White" Name="Bd" SnapsToDevicePixels="True">
<ContentPresenter Content="{TemplateBinding ContentControl.Content}" ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}" ContentStringFormat="{TemplateBinding ContentControl.ContentStringFormat}" HorizontalAlignment="{TemplateBinding Control.HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding Control.VerticalContentAlignment}" SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
</Border>
<Label Height="3"></Label>
</StackPanel>
</ControlTemplate>
// trigger code omitted
<Style TargetType="ListBoxItem">
<Setter Property="Control.Template" Value="{StaticResource CustomListBoxItem}"></Setter>
<Setter Property="ItemsControl.DisplayMemberPath" Value="MatchText"></Setter>
</Style>
XAML
<ListBox x:Name="listBox" DisplayMemberPath="MyCustomText">
The DataContext of listBox is set using code. If I omit setting CustomListBoxItem as the control template, than it works as expected. How do you enable DisplayMemberPath when using custom control templates for ListBox and ListBoxItem?
I have a simple xaml example and I want to change CornerRadius property, which is set through ControlTemplate of Button. I need a way to change it through Button. One use case is: I have 2 buttons, one sets to "BigRadius" and another one sets to "SmallRadius". If I change the default one on Border, then both buttons will have the same CornerRadius. Is there a way to do this in XAML only?
<Window x:Class="StyleDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Style TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border CornerRadius="5" BorderBrush="Blue"
BorderThickness="5"
Width="80"
Height="40"
x:Name="BaseBorder">
<ContentPresenter Content="{Binding Path=Content, RelativeSource={RelativeSource TemplatedParent}}" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="Grid" x:Name="GridWithMarginStyle">
<Setter Property="Margin" Value="12"></Setter>
</Style>
</Window.Resources>
<StackPanel>
<!--This button will have a big corner radius-->
<Button Name="Ok" Content="Ok"></Button>
<!--This button will have a small corner radius-->
<Button Name="CancelBtn" Click="CancelBtn_Click">Cancel</Button>
</StackPanel>
</Window>
You will need two styles for the Button to achieve what you are doing or create a Custom Button to implement CornerRadius as DependencyProperty, and bind it with CornerRadius of Border in ControlTemplate.
<Style TargetType="Button" x:Key="LargeRadiusStyle">
<Setter Property="Background" Value="White" />
<Setter Property="TextBlock.TextAlignment" Value="Center" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border CornerRadius="10" Background="White" BorderBrush="Black" BorderThickness="1" >
<ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="Button" x:Key="SmallRadiusStyle">
<Setter Property="Background" Value="White" />
<Setter Property="TextBlock.TextAlignment" Value="Center" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border CornerRadius="3" Background="White" BorderBrush="Black" BorderThickness="1" >
<ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Not sure what you have against DPs. You need SOMETHING to tell the button whether you want the big radius or the small radius. WPF can't read your mind (yet) :). If you don't want a custom button class, then you can use an attached property.
I've created a WPF Custom Control, I put it on a form and give it a height and a width - all works fine. I'm referencing Height and Width using TemplateBinding in the control, so I need these to be set.
Should I decide to resize the control using the gui, the height and width disappear completely and the control formatting goes wrong.
How do I get the new height and width of the control and set it when this happens?
Posting code as requested:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:GraphControls">
<Style TargetType="{x:Type local:ContourPlot}" >
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:ContourPlot}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<Viewbox>
<Border BorderBrush="Black" BorderThickness="1">
<Canvas x:Name="cvGraph" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" >
<Rectangle Canvas.Left="40" Canvas.Top="31" Width="48" Height="41" Fill="AliceBlue"/>
</Canvas>
</Border>
</Viewbox>
<Canvas Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" >
<Label x:Name="lblTest" Canvas.Left="0" Canvas.Top="10" Content="Label" FontSize="12" />
</Canvas>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Control is used in a form as follows:
<Window x:Class="GraphWrapper.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:gc="clr-namespace:GraphControls;assembly=GraphControls"
Title="MainWindow" Height="350" Width="525">
<Grid>
<gc:ContourPlot Background="#FFC3EAC3" Margin="65,42,128,118" Width="310" Height="150"/>
</Grid>
</Window>
As previously stated, when the control is resized via the gui, the Width and Height properties disappear.
<Style TargetType="{x:Type local:ContourPlot}" >
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:ContourPlot}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Width="{TemplateBinding Width}"
Height="{TemplateBinding Height}">
<Grid>
<Viewbox Width="{TemplateBinding Width}"
Height="{TemplateBinding Height}">
<Border BorderBrush="Black" BorderThickness="1">
<Canvas x:Name="cvGraph" >
<Rectangle Canvas.Left="40" Canvas.Top="31" Width="48" Height="41" Fill="AliceBlue"/>
</Canvas>
</Border>
</Viewbox>
<Canvas >
<Label x:Name="lblTest" Canvas.Left="0" Canvas.Top="10" Content="Label" FontSize="12" />
</Canvas>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
The Templated width and Height are not recommended to use in multiple controls inside its control Template. In Your case, Height and Width are going to be same as if you set like above.
More over you have placed the ViewBox and the Canvas in same area so its going to be overlap with same width and height. The problem might be with the Viewbox.
I have a WPF ListView that contains a GridView. I want the selected row to look "flat" and not 3d style.
Dose anyone know how to do this?
Thanks,
Smadar
The 3D look is part of the default style. To change this you need to replace the ControlTemplate for ListViewItem. Here's a simple example which produces the following:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<ListView>
<ListView.View>
<GridView>
<GridViewColumn Header="A"/>
</GridView>
</ListView.View>
<ListView.Items>
<ListViewItem Content="Item 1"/>
<ListViewItem Content="Item 2"/>
<ListViewItem Content="Item 3"/>
</ListView.Items>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListViewItem">
<Border CornerRadius="2" SnapsToDevicePixels="True"
BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}"
Background="{TemplateBinding Background}">
<Border Name="InnerBorder" CornerRadius="1" BorderThickness="1">
<Grid>
<Grid.RowDefinitions>
<RowDefinition MaxHeight="11" />
<RowDefinition />
</Grid.RowDefinitions>
<Rectangle Name="UpperHighlight" Visibility="Collapsed" Fill="#75FFFFFF" />
<GridViewRowPresenter Grid.RowSpan="2"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</Grid>
</Border>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="LightBlue"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
</ListView>
</Grid>
</Window>
Note: The default templates are located here http://msdn.microsoft.com/en-us/library/ms788747.aspx. Since there is no way to change part of a ControlTemplate or base one off of an existing template, I usually try to keep as much of the default template as I can, and only change the parts I care about. It's a little verbose but should do what you're looking for.