How to change control in style programmatically - c#

I have a button style. I can't change CornerRadius for Border, what is in Template.
Style:
<Style TargetType="Button" x:Key="Circle">
<Setter Property="Background" Value="#373737"/>
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Name="Bord1" CornerRadius="20" Background="{TemplateBinding Background}">
<Grid>
<TextBlock Name="tx" Text="{TemplateBinding Content}" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="{TemplateBinding FontSize}" Foreground="White"/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#EBEBEB" />
<Setter TargetName="tx" Property="Foreground" Value="Black"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" >
<Setter.Value>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1" >
<GradientStop Color="#F3F3F3" Offset="0.35"/>
<GradientStop Color="#FFC9C7BA" Offset="0.95"/>
<GradientStop Color="#CDCDCD" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter TargetName="tx" Property="RenderTransform" >
<Setter.Value>
<TranslateTransform Y="1.0" />
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I wrote this code, but it does not help me.
Style A = Application.Current.Resources["Circle"] as Style;
Setter A1 = (Setter)A.Setters[2];
ControlTemplate C1 = (ControlTemplate)A1.Value;
Border B = (Border)C1.LoadContent();
B.SetValue(Border.CornerRadiusProperty, new CornerRadius(2));

You can use your style like this:
Change the Fixed Cornerradius in your Template to a Template Binding
Create a new Class like:
public class MyButton : Button {
public static readonly DependencyProperty CornerRadiusProperty = DependencyProperty.Register(
"CornerRadius", typeof(CornerRadius), typeof(MyButton), new PropertyMetadata(default(CornerRadius)));
public CornerRadius CornerRadius {
get { return (CornerRadius) GetValue(CornerRadiusProperty); }
set { SetValue(CornerRadiusProperty, value); }
}
}
use the class like this in your style and xaml:
<Window x:Class="WpfApp1.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:WpfApp1"
mc:Ignorable="d"
Title="{Binding Path=Content.Title, ElementName=MainFrame}" Height="450" Width="800">
<Window.Resources>
<Style TargetType="local:MyButton" x:Key="Circle">
<Setter Property="Background" Value="#373737"/>
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:MyButton">
<Border Name="Bord1" CornerRadius="{TemplateBinding CornerRadius}" Background="{TemplateBinding Background}">
<Grid>
<TextBlock Name="tx" Text="{TemplateBinding Content}" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="{TemplateBinding FontSize}" Foreground="White"/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#EBEBEB" />
<Setter TargetName="tx" Property="Foreground" Value="Black"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" >
<Setter.Value>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1" >
<GradientStop Color="#F3F3F3" Offset="0.35"/>
<GradientStop Color="#FFC9C7BA" Offset="0.95"/>
<GradientStop Color="#CDCDCD" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter TargetName="tx" Property="RenderTransform" >
<Setter.Value>
<TranslateTransform Y="1.0" />
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<StackPanel>
<local:MyButton Style="{StaticResource Circle}" CornerRadius="10"></local:MyButton>
</StackPanel>
</Window>
UPDATE:
Or you can Change the CornerRadius for your Border programatically like:
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
Loaded += WasLoaded;
}
private void WasLoaded(object sender, RoutedEventArgs e) {
var children = VisualTreeHelper.GetChildrenRecursive(Button1);
foreach (var child in children.OfType<Border>()) {
if (child.Name == "Bord1") {
child.CornerRadius = new CornerRadius(1);
break;
}
}
}
}
public static class VisualTreeHelper {
/// <summary>
/// Enumerates through element's children in the visual tree.
/// </summary>
public static IEnumerable<DependencyObject> GetChildrenRecursive(this DependencyObject element) {
if (element == null) {
throw new ArgumentNullException("element");
}
for (var i = 0; i < System.Windows.Media.VisualTreeHelper.GetChildrenCount(element); i++) {
var child = System.Windows.Media.VisualTreeHelper.GetChild(element, i);
yield return child;
foreach (var item in child.GetChildrenRecursive()) {
yield return item;
}
}
}
}

Related

How to remove gradient effect appearing for IsMouseOver in WPF ListViewItem's style?

In the following Window I define a trigger for IsMouseOver. The background color is changed correctly, but it has an gradient effect. See the pic below. How to get rid of the effect?
Only Theme.DataGrid.Row.Background.Hover is moved from separate style file to code excerpt below.
<Window x:Class="MyCompany.Application.Shared.UI.Dialogs.SomeWindow
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"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525" Background="#FFF3F3F7">
<Window.Resources>
<SolidColorBrush x:Key="Theme.DataGrid.Row.BorderBrush" Color="#FFF3F3F7" options:Freeze="True" />
<SolidColorBrush x:Key="Theme.DataGrid.Row.Background" Color="White" options:Freeze="True" />
<SolidColorBrush x:Key="Theme.DataGrid.Row.Background.Hover" Color="#FFAEAEB6" options:Freeze="True" />
<SolidColorBrush x:Key="Theme.DataGrid.Row.Background.Active" Color="#FF0D6AA8" options:Freeze="True" />
<SolidColorBrush x:Key="Theme.DataGrid.Row.Background.HoverSelected" Color="#FF009AD9" options:Freeze="True" />
<SolidColorBrush x:Key="Theme.DataGrid.Row.Background.Disabled" Color="#FFAEAEB6" options:Freeze="True" />
<SolidColorBrush x:Key="Theme.DataGrid.Row.Foreground.Selected" Color="White" options:Freeze="True" />
<Style x:Key="GridView.ColumnHeader.Gripper.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>
<Style TargetType="{x:Type GridViewColumnHeader}" >
<EventSetter Event="FrameworkElement.Loaded" Handler="GridViewColumnHeader_Loaded"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Background" Value="{StaticResource Theme.DataGrid.ColumnHeader.Background}"/>
<Setter Property="Foreground" Value="Black"/>
<Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GridViewColumnHeader}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="1" />
</Grid.ColumnDefinitions>
<Border Grid.Column="0" x:Name="Border" BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}">
<ContentPresenter Margin="{TemplateBinding Padding}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</Border>
<Thumb Grid.Column="1" x:Name="PART_HeaderGripper" HorizontalAlignment="Right" Style="{DynamicResource Theme.DataGrid.ColumnHeader.Gripper.Style}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type ListView}" >
<Setter Property="BorderThickness" Value="{DynamicResource Theme.DataGrid.BorderThickness}"/>
<Setter Property="Background" Value="{StaticResource Theme.TreeView.Background}"/>
</Style>
<Style TargetType="{x:Type ListViewItem}" >
<Setter Property="Background" Value="White" />
<Setter Property="Foreground" Value="{DynamicResource Theme.DataGrid.Row.Foreground}" />
<Setter Property="VerticalAlignment" Value="Stretch"/>
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="Padding" Value="{DynamicResource Theme.DataGrid.Cell.Padding}"/>
<Setter Property="Margin" Value="1"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{DynamicResource Theme.DataGrid.Row.Background.Hover}" />
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="{DynamicResource Theme.DataGrid.Row.Background.Active}"
<Setter Property="Foreground" Value="{DynamicResource Theme.DataGrid.Row.Background.Selected}" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Background" Value="{DynamicResource Theme.DataGrid.Row.Background.Disabled}" />
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="True" />
<Condition Property="IsSelected" Value="True" />
</MultiTrigger.Conditions>
<Setter Property="Background" Value="{DynamicResource Theme.DataGrid.Row.Background.HoverSelected}" />
</MultiTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<StackPanel>
<CheckBox Content="IsGrouped" IsChecked="{Binding IsGrouped}"/>
<ListView Margin="10" ItemsSource="{Binding Users}">
<ListView.View>
<GridView AllowsColumnReorder="False">
<GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}" />
<GridViewColumn Header="Age" DisplayMemberBinding="{Binding Age}" />
<GridViewColumn Header="Mail" DisplayMemberBinding="{Binding Mail}" />
<GridViewColumn Header="Group" DisplayMemberBinding="{Binding Group}" />
</ListView>
</StackPanel>
</Window>
ViewModel (note that this uses our own ViewModel-class that i.e raises PropertyChanged events)
namespace MyCompany.Application.Shared.UI.Dialogs
{
public class User
{
public string Name { get; set; }
public int Age { get; set; }
public string Mail { get; set; }
public string Group { get; set; }
}
public class SomeWindowViewModel : ViewModel
{
List<User> items = new List<User>();
IEnumerable<User> GetUsers()
{
foreach (var item in items)
{
yield return item;
}
}
public ICollectionView Users { get; }
private bool _isGrouped = false;
public bool IsGrouped
{
get { return _isGrouped; }
set
{
_isGrouped = value;
if (value)
{
Users.GroupDescriptions.Add(new PropertyGroupDescription("Group"));
}
else
{
Users.GroupDescriptions.Clear();
}
}
}
public SomeWindowViewModel()
{
items.Add(new User() { Name = "John Doe", Age = 42, Mail = "john#doe-family.com", Group = "OneGroup1" });
items.Add(new User() { Name = "Jane Doe", Age = 39, Mail = "jane#doe-family.com", Group = "OneGroup1" });
items.Add(new User() { Name = "Sammy Doe", Age = 7, Mail = "sammy.doe#gmail.com", Group = "TwoGroup2" });
items.Add(new User() { Name = "Pentti Doe", Age = 7, Mail = "pena.doe#gmail.com", Group = "TwoGroup2" });
Users = CollectionViewSource.GetDefaultView(GetUsers());
}
}
}
I had some issues with the given code sample, e.g. missing resources or additional options:Freeze="true" which could not be resolved, therefore my solution may look a little different, but I think it does what you want: it removes the gradient effect.
The issue is that the default ListViewItem template has triggers which change the background (as you have found out as well) and the way around is to use a simplified ControlTemplate without any triggers.
This example of a simplified template works and you can put it in your {x:Type ListViewItem} to get a look like shown in the pictures below.
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<Border Padding="{TemplateBinding Padding}"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
SnapsToDevicePixels="true">
<GridViewRowPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
Using that template, this is what it will look like if you first selected "Sammy Doe 7" and then hover over "Jane Doe 39",
and this is how it looks when you select (e.g. click on) "Jane Doe 39":
I'm not entirely sure what you mean with
as jsanalytics points out control template results in rows to be class names and not the data
but as far as I understand it, above code should not lead to that behavior. If it does, let me know and I will find another solution.

TextBox not resetting focus when reopening the dropdown in a ComboBox

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.

Control template trigger not firing correctly after property change in code behind [WPF]

I'm making a periodic table of elements wpf application and have made my buttons like this:
<!-- RoundedButton.xaml -->
<Style x:Key="ButtonFocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Border>
<Rectangle SnapsToDevicePixels="true" Margin="4" Stroke="Black" StrokeDashArray="1 2" StrokeThickness="1"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="RoundedButton" TargetType="{x:Type Button}" x:Name="butt">
<Setter Property="FocusVisualStyle" Value="{StaticResource ButtonFocusVisual}"/>
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="BorderThickness" Value="3"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Padding" Value="0,0,1,1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border CornerRadius="12,12,12,12" BorderThickness="3,3,3,3" RenderTransformOrigin="0.5,0.5" x:Name="border" BorderBrush="Transparent">
<Border.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="1" ScaleY="1"/>
<SkewTransform AngleX="0" AngleY="0"/>
<RotateTransform Angle="0"/>
<TranslateTransform X="0" Y="0"/>
</TransformGroup>
</Border.RenderTransform>
<Border Background="{TemplateBinding Background}" CornerRadius="12,12,12,12" x:Name="bordertrue">
<Grid>
<Border Opacity="0" x:Name="Shine" Width="Auto" Height="Auto" CornerRadius="12,12,10,10" Margin="0,0,0,0">
<Border.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="Indigo" Offset="0"/>
<GradientStop Color="Crimson" Offset="0.5"/>
<GradientStop Color="Crimson" Offset="0.5"/>
<GradientStop Color="Indigo" Offset="1"/>
</LinearGradientBrush>
</Border.Background>
</Border>
<ContentPresenter VerticalAlignment="Center" Grid.RowSpan="2" HorizontalAlignment="Center" x:Name="contentPresenter"/>
</Grid>
</Border>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" TargetName="border" Value="1"/>
<Setter Property="Opacity" TargetName="contentPresenter" Value="0.5"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="RenderTransform" TargetName="border">
<Setter.Value>
<TransformGroup>
<ScaleTransform ScaleX="0.9" ScaleY="0.9"/>
<SkewTransform AngleX="0" AngleY="0"/>
<RotateTransform Angle="0"/>
<TranslateTransform X="0" Y="0"/>
</TransformGroup>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Opacity" TargetName="Shine" Value="1"/>
<Setter Property="BorderBrush" TargetName="border" Value="Gold"/>
<Setter Property="Foreground" Value="Gold" />
<Setter Property="FontWeight" Value="ExtraBold"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And this is working perfectly on mouseover. However in my app I have a combination of textbox and listbox which makes me a searchbox. Whenever I search for a particular element I wish to make the same "Shine button" effect as on mouseover in style above
I've tried to do it like this:
private void highlight(string elementName, bool MultiOrSingle)
{
LinearGradientBrush gradient1 = new LinearGradientBrush();
gradient1.StartPoint = new Point(0.5, 0);
gradient1.EndPoint = new Point(0.5, 1);
gradient1.GradientStops.Add(new GradientStop(Colors.Indigo, 0));
gradient1.GradientStops.Add(new GradientStop(Colors.Crimson, 0.5));
gradient1.GradientStops.Add(new GradientStop(Colors.Crimson, 0.5));
gradient1.GradientStops.Add(new GradientStop(Colors.Indigo, 1));
if (MultiOrSingle == true)
{
foreach (Button elementButton in VisualChildren.FindVisualChildren<Button>(this))
{
if (listBox.Items.Contains(elementButton.Name) == true)
{
elementButton.Background = gradient1;
elementButton.FontWeight = FontWeights.Bold;
elementButton.Foreground = Brushes.Gold;
elementButton.BorderBrush = Brushes.Gold;
}
else
{
elementButton.Background = previousBackgroundColors[elementButton.Name];
elementButton.Foreground = previousForegroundColors[elementButton.Name];
}
}
foreach (Button elementButton in VisualChildren.FindVisualChildren<Button>(this))
{
if (elementButton.Name != "play_quiz" &&
elementButton.Name != "show_scoreboard" &&
elementButton.Name != "update" &&
elementButton.Name != "DragDropGames" &&
listBox.Items.Contains(elementButton.Name) == false)
{
elementButton.Background = Brushes.Gainsboro;
elementButton.BorderBrush = Brushes.DarkBlue;
elementButton.FontWeight = FontWeights.Normal;
elementButton.Foreground = Brushes.Black;
}
}
}
else
{
foreach (Button elementButton in VisualChildren.FindVisualChildren<Button>(this))
{
if (elementName == elementButton.Name)
{
elementButton.Background = gradient1;
elementButton.BorderBrush = Brushes.Gold;
elementButton.FontWeight = FontWeights.Bold;
elementButton.Foreground = Brushes.Gold;
}
else
{
elementButton.Background = previousBackgroundColors[elementButton.Name];
elementButton.Foreground = previousForegroundColors[elementButton.Name];
}
}
foreach (Button elementButton in VisualChildren.FindVisualChildren<Button>(this))
{
if (elementButton.Name != "play_quiz" &&
elementButton.Name != "show_scoreboard" &&
elementButton.Name != "update" &&
elementButton.Name != "DragDropGames" &&
elementName != elementButton.Name)
{
elementButton.Background = Brushes.Gainsboro;
elementButton.BorderBrush = Brushes.DarkBlue;
elementButton.FontWeight = FontWeights.Normal;
elementButton.Foreground = Brushes.Black;
}
}
}
with just setting backgrounds brushes etc etc....
However I encountered 2 problems. When doing this in code behind i can change everything but my border brush will remain as it is determined in xaml style I can't change it in code behind don't know why? And after calling this function when I mouse over the buttons they will Shine...however property foreground won't be changed to gold? It will remain black
to demonstrate :
So this is my mouseover "Shine". When I go with mouse over the button it will change it's look like this
So this is my problem I have searched for H..it came back with few results and called function from above as "multi" and selected all results
However this didn't work "elementButton.BorderBrush = Brushes.Gold" it remained transparent as in xaml. And suddenly my Mouseover shine is not the same anymore it's
<Setter Property="Foreground" Value="Gold" />
<Setter Property="FontWeight" Value="ExtraBold"/>
don't seem to be triggering after the function call
To sum it up. I would like to have the same look of the button and shine effect for all my textbox searches
Your Trigger changes the BorderBrush on element named "Border". However in your code behind you are setting the BorderBrush on the button, which does nothing because you don't use the property BorderBrush anywhere in your template. What you need to do is TemplateBinding the Button's BorderBrush property to the template, like the following:
<Border CornerRadius="12,12,12,12"
BorderThickness="3,3,3,3"
RenderTransformOrigin="0.5,0.5"
x:Name="border"
BorderBrush="{TemplateBinding BorderBrush}">
In order to get the FontWeight and Foreground to trigger when the mouse is over the button when properties is set in code behind, one possible solution is the following.
Set the TextBlock property in the ContentPresenter and then use TemplateBinding to set the value.
<ContentPresenter TextBlock.Foreground="{TemplateBinding Foreground}"
TextBlock.FontWeight="{TemplateBinding FontWeight}"
VerticalAlignment="Center"
Grid.RowSpan="2"
HorizontalAlignment="Center"
x:Name="contentPresenter"/>
<Setter Property="TextBlock.Foreground" TargetName="contentPresenter" Value="White" />
<Setter Property="TextBlock.FontWeight" TargetName="contentPresenter" Value="ExtraBold"/>

Change GridView ColumnHeaderContainerStyle with a binded View

I have a binded ListView like so :
<ListView Margin="0,10,8,-10" BorderThickness="2" BorderBrush="AliceBlue"
ItemsSource="{Binding PackageBrowser.Documents}"
SelectedItem="{Binding SelectedDocument}"
View="{Binding PackageBrowser.ColumnConfig, Converter={Converters:ConfigToDynamicGridViewConverter}}">... </ListView>
The main purpose of this binding is to generate dynamic column.
Here is my Converter:
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var config = value as ColumnConfig;
var gridView = new GridView();
var actualColumn = new GridViewColumn() { Header = "Name", DisplayMemberBinding = new Binding("Name") };
gridView.Columns.Add(actualColumn);
if (config != null)
{
foreach (var column in config.Columns)
{
var binding = new Binding(string.Format(CultureInfo.InvariantCulture, "ColumnValues[{0}]", column.Name));
gridView.Columns.Add(new GridViewColumn { Header = column.Header, DisplayMemberBinding = binding });
}
foreach (GridViewColumn c in gridView.Columns)
{
// Code below was found in GridViewColumnHeader.OnGripperDoubleClicked() event handler (using Reflector)
// i.e. it is the same code that is executed when the gripper is double clicked
// if (adjustAllColumns || App.StaticGabeLib.FieldDefsGrid[colNum].DispGrid)
if (double.IsNaN(c.Width))
{
c.Width = c.ActualWidth;
}
c.Width = double.NaN;
}
}
return gridView;
}
My question is :
How can I modify the ColumnHeaderContainerStyle of my gridView so all the column cannot be resize.
Something like that but in the code behind :
<GridView.ColumnHeaderContainerStyle>
<Style TargetType="{x:Type GridViewColumnHeader}">
<Setter Property="IsEnabled" Value="False"/>
</Style>
</GridView.ColumnHeaderContainerStyle>
I guess, You might be written missing code (ColumnHeaderContainerStyle). If you write any style for ColumnHeaderStyle.You must complete all features(If you want to make different designs).For example : Thumb,ContentPresenter etc.I have written a listview style code for you.
(Sorry,I dont know very well English.I hope this is what you want)
Here is code:
<Style x:Key="GridViewColumnHeaderGripper" TargetType="Thumb">
<Setter Property="Width" Value="18"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Thumb}">
<Border Padding="{TemplateBinding Padding}" Background="Transparent">
<Rectangle HorizontalAlignment="Center" Width="1" Fill="#FFD4D4D4"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="{x:Type GridViewColumnHeader}" TargetType="GridViewColumnHeader">
<Setter Property="FontFamily" Value="Tahoma"/>
<Setter Property="Foreground" Value="#FF003362"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Padding" Value="5"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="GridViewColumnHeader">
<Grid>
<Border Background="White" BorderBrush="#FFD4D4D4" BorderThickness="1,1,0,1" Name="HeaderBorder" Padding="{TemplateBinding Padding}">
<ContentPresenter Name="HeaderContent" Content="{TemplateBinding Content}" Margin="0,0,0,1" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</Border>
<Thumb x:Name="PART_HeaderGripper" HorizontalAlignment="Right" Margin="0,0,-9,0" Style="{StaticResource GridViewColumnHeaderGripper}"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsPressed" Value="true">
<Setter TargetName="HeaderContent" Property="Margin" Value="1,1,0,0"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Opacity" Value=".5" TargetName="HeaderBorder"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="Role" Value="Floating">
<Setter Property="Opacity" Value="0.7" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="GridViewColumnHeader">
<Canvas Name="PART_FloatingHeaderCanvas">
<Rectangle Fill="#60000000" Width="{TemplateBinding ActualWidth}" Height="{TemplateBinding ActualHeight}"/>
</Canvas>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>

Binding custom ItemsControl

I’m trying to create custom Itemscontrol class to display a group of different shapes.
To speed up process, I have reused source code from CodeProject (WPF Diagram Designer - Part 4) where all implementation is done but shapes are added from XAML code. For my purposes, I need to add them from code behind (dynamically) so I bound custom Itemscontrol to list of ObservableCollection. Now, instead of shapes be presented like this:
I get something like this:
Can somebody tell me what I’m doing wrong?
Any help will be appreciated. Thanks in advance.
XAML:
<s:Toolbox x:Key="FlowChartStencils" ItemsSource="{Binding ElementName=MyDesigner, Path=ToolboxDataItems}" ItemTemplate="{StaticResource toolboxItemTemplate}" ItemSize="190,150" SnapsToDevicePixels="True" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
</s:Toolbox>
<DataTemplate x:Key="toolboxItemTemplate">
<Grid Margin="5,5,5,5">
<Path Style="{StaticResource Process}">
<s:DesignerItem.DragThumbTemplate>
<ControlTemplate>
<Path Style="{StaticResource Process_DragThumb}"/>
</ControlTemplate>
</s:DesignerItem.DragThumbTemplate>
</Path>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text=" {Binding Title}" IsHitTestVisible="False" FontWeight="Bold"/>
</Grid>
</DataTemplate>
<Style x:Key="Process" TargetType="Path" BasedOn="{StaticResource FlowChartItemStyle}">
<Setter Property="Data" Value="M 0,0 H 60 V40 H 0 Z"/>
</Style>
<Style x:Key="Process_DragThumb" TargetType="Path" BasedOn="{StaticResource Process}">
<Setter Property="IsHitTestVisible" Value="true"/>
<Setter Property="Fill" Value="Transparent"/>
<Setter Property="Stroke" Value="Transparent"/>
</Style>
<Style x:Key="FlowChartItemStyle" TargetType="Path">
<Setter Property="Fill" Value="{StaticResource ItemBrush}"/>
<Setter Property="Stroke" Value="{StaticResource ItemStroke}"/>
<Setter Property="StrokeThickness" Value="1"/>
<Setter Property="StrokeLineJoin" Value="Round"/>
<Setter Property="Stretch" Value="Fill"/>
<Setter Property="IsHitTestVisible" Value="False"/>
<Setter Property="SnapsToDevicePixels" Value="True"/>
</Style>
<Brush x:Key="ItemStroke">#FFD69436</Brush>
<LinearGradientBrush x:Key="ItemBrush" StartPoint="0,0" EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStop Color="#FAFBE9" Offset="0" />
<GradientStop Color="Orange" Offset="1" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
Code behind:
// Implements ItemsControl for ToolboxItems
public class Toolbox : ItemsControl
{
// Defines the ItemHeight and ItemWidth properties of
// the WrapPanel used for this Toolbox
public Size ItemSize
{
get { return itemSize; }
set { itemSize = value; }
}
private Size itemSize = new Size(50, 50);
// Creates or identifies the element that is used to display the given item.
protected override DependencyObject GetContainerForItemOverride()
{
return new ToolboxItem();
}
// Determines if the specified item is (or is eligible to be) its own container.
protected override bool IsItemItsOwnContainerOverride(object item)
{
return (item is ToolboxItem);
}
}
// Represents a selectable item in the Toolbox/>.
public class ToolboxItem : ContentControl
{
…
}
public class ToolboxDataItem : DependencyObject
{
public string Title
{
get { return (string)GetValue(TitleProperty); }
set { SetValue(TitleProperty, value); }
}
public static readonly DependencyProperty TitleProperty =
DependencyProperty.Register( "Title", typeof( string ),
typeof(ToolboxDataItem), new UIPropertyMetadata(""));
public ToolboxDataItem(string title)
{
Title = title;
}
}
public partial class DesignerCanvas : Canvas
{
private ObservableCollection<ToolboxDataItem> toolboxDataItems = new ObservableCollection<ToolboxDataItem>();
public ObservableCollection<ToolboxDataItem> ToolboxDataItems
{
get { return toolboxDataItems; }
}
public DesignerCanvas()
{
ToolboxDataItem toolboxDataItem = new ToolboxDataItem("123");
ToolboxDataItems.Add(toolboxDataItem );
toolboxDataItem = new ToolboxDataItem("456");
ToolboxDataItems.Add(toolboxDataItem );
}
}
MyDesigner:
<s:DesignerCanvas Focusable="true" x:Name="MyDesigner"
Background="{StaticResource WindowBackgroundBrush}" FocusVisualStyle="{x:Null}"
ContextMenu="{StaticResource DesignerCanvasContextMenu}"/>
So I started by trying to get an app going with the code you shared but the styles were all in an incorrect order, so after the styles were set correctly I got arround to an example like this:
<Window.Resources>
<ResourceDictionary>
<Brush x:Key="ItemStroke">#FFD69436</Brush>
<LinearGradientBrush x:Key="ItemBrush" StartPoint="0,0" EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStop Color="#FAFBE9" Offset="0" />
<GradientStop Color="Orange" Offset="1" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
<Style x:Key="FlowChartItemStyle" TargetType="Path">
<Setter Property="Fill" Value="{StaticResource ItemBrush}"/>
<Setter Property="Stroke" Value="{StaticResource ItemStroke}"/>
<Setter Property="StrokeThickness" Value="1"/>
<Setter Property="StrokeLineJoin" Value="Round"/>
<Setter Property="Stretch" Value="Fill"/>
<Setter Property="IsHitTestVisible" Value="False"/>
<Setter Property="SnapsToDevicePixels" Value="True"/>
</Style>
<Style x:Key="Process" TargetType="Path" BasedOn="{StaticResource FlowChartItemStyle}">
<Setter Property="Data" Value="M 0,0 H 60 V40 H 0 Z"/>
</Style>
<DataTemplate x:Key="toolboxItemTemplate">
<Grid Margin="5,5,5,5">
<Path Style="{StaticResource Process}">
</Path>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding Title}" IsHitTestVisible="False" FontWeight="Bold"/>
</Grid>
</DataTemplate>
<Style x:Key="Process_DragThumb" TargetType="Path" BasedOn="{StaticResource Process}">
<Setter Property="IsHitTestVisible" Value="true"/>
<Setter Property="Fill" Value="Transparent"/>
<Setter Property="Stroke" Value="Transparent"/>
</Style>
</ResourceDictionary>
</Window.Resources>
<Grid>
<ItemsControl Background="Yellow"
ItemsSource="{Binding ToolboxDataItems}"
ItemTemplate="{StaticResource toolboxItemTemplate}"
SnapsToDevicePixels="True"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
</ItemsControl>
</Grid>
So if you check this example to yours then your problem might be in one of two places:
1) The Text binding of the TextBlock (notice the space before the {):
2) Or the Path inside the ItemsSource binding of the toolbox
<s:Toolbox x:Key="FlowChartStencils" ItemsSource="{Binding ElementName=MyDesigner, Path=ToolboxDataItems}" ItemTemplate="{StaticResource toolboxItemTemplate}" ItemSize="190,150" SnapsToDevicePixels="True" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
Here try something like ItemsSource="{Binding ToolboxDataItems, ElementName=MyDesigner}"

Categories

Resources