I want to implement a button, that have 4 stage (Stage1/Stage2/Stage3/Stage4)
and I want to click on it, the text and style will change (Stage1 -> Stage2 -> Stage3 -> Stage4 -> Stage1 -> ....)
Here is my XAML button code.
<ControlTemplate x:Key="StageButton" TargetType="{x:Type Button}">
<Button
Width="102"
Tag="1"
Click="Hello_Click"
BorderThickness="0"
Background="Transparent"
Cursor="Hand">
<Border
BorderThickness="2"
BorderBrush="Gray"
CornerRadius="10"
Background="Green"
Width="100"
Height="20"
>
<TextBlock
Width="100"
Foreground="White"
FontWeight="Bold"
FontSize="12"
Padding="14 1 0 0"
Text="Stage1"
/>
</Border>
</Button>
</ControlTemplate>
Thanks for help
You can make a custom Button with incremental stage (starting at 1) functionality:
using System;
using System.Windows;
using System.Windows.Controls;
public class StagedButton : Button
{
public int Stage
{
get { return (int)GetValue(StageProperty); }
set { SetValue(StageProperty, value); }
}
public static readonly DependencyProperty StageProperty =
DependencyProperty.Register("Stage", typeof(int), typeof(StagedButton),
new FrameworkPropertyMetadata(1, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, null,
(d, baseValue) => Math.Min(((StagedButton)d).StageCount, Math.Max(1, (int)baseValue))));
public int StageCount
{
get { return (int)GetValue(StageCountProperty); }
set { SetValue(StageCountProperty, value); }
}
public static readonly DependencyProperty StageCountProperty =
DependencyProperty.Register("StageCount", typeof(int), typeof(StagedButton),
new PropertyMetadata(1, null,
(d, baseValue) => Math.Max(1, (int)baseValue)));
protected override void OnClick()
{
var stage = Stage;
Stage = (++stage <= StageCount) ? stage : 1;
base.OnClick();
}
}
StageCount is the number of stages. (d, baseValue) => ... part is to filter out invalid values.
Then define a Style for this Button.
<Style x:Key="StagedButtonStyle" TargetType="{x:Type local:StagedButton}">
<Setter Property="Width" Value="100"/>
<Setter Property="Height" Value="20"/>
<Setter Property="BorderThickness" Value="2"/>
<Setter Property="BorderBrush" Value="LightGray"/>
<Setter Property="Background" Value="#c42a1c"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="TextElement.FontWeight" Value="Bold"/>
<Setter Property="TextElement.FontSize" Value="12"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:StagedButton}">
<Border BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}"
Background="{TemplateBinding Background}"
CornerRadius="10">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<!-- Set 4 to StageCount. -->
<Setter Property="StageCount" Value="4"/>
<Style.Triggers>
<!-- Define Background for each Stage (up to 4) except default one. -->
<Trigger Property="Stage" Value="2">
<Setter Property="Background" Value="DodgerBlue"/>
</Trigger>
<Trigger Property="Stage" Value="3">
<Setter Property="Background" Value="Green"/>
</Trigger>
<Trigger Property="Stage" Value="4">
<Setter Property="Background" Value="DimGray"/>
</Trigger>
</Style.Triggers>
</Style>
You can increase the number of stages if you wish.
Its usage will be as follows:
<local:StagedButton Style="{StaticResource StagedButtonStyle}">
<TextBlock Text="{Binding Stage, RelativeSource={RelativeSource AncestorType={x:Type local:StagedButton}}, StringFormat=Stage {0}}"/>
</local:StagedButton>
Related
I bound ViewScale to Grid's ScaleTransform and when the app starts it correctly scales by 2. But when I change ViewScale by pressing F12, it doesn't trigger ScaleTransform update even though the property value is changed.
Here is the code:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace test
{
public partial class MainWindow : Window
{
public event PropertyChangedEventHandler PropertyChanged;
protected void SetField<T> ( ref T field, T value, string propertyName )
{
if ( !EqualityComparer<T>.Default.Equals ( field, value ) )
{
field = value;
PropertyChanged?.Invoke ( this, new PropertyChangedEventArgs ( propertyName ) );
}
}
decimal viewScale = 2;
public decimal ViewScale
{
get => this.viewScale;
set => SetField ( ref this.viewScale, value,
"ViewScale"
);
}
ObservableCollection<Coin> _coins;
public ObservableCollection<Coin> Coins { get => _coins; set => SetField ( ref _coins, value, nameof ( _coins ) ); }
public ICollectionView CollectionView;
public MainWindow ( )
{
this.Coins = new ObservableCollection<Coin> ( );
for ( int i = 0 ; i < 100 ; ++i )
this.Coins.Add ( new Coin ( "Coin 1", i ) );
this.DataContext = this;
InitializeComponent ( );
this.PreviewKeyDown += MainWindow_PreviewKeyDown;
}
void MainWindow_PreviewKeyDown ( object sender, KeyEventArgs e )
{
Console.WriteLine ( e.Key );
if ( e.Key == Key.Home )
{
this.dataGrid.ScrollIntoView ( this.dataGrid.Items [ this.dataGrid.Items.Count - 1 ] );
this.dataGrid.UpdateLayout ( );
this.dataGrid.ScrollIntoView ( this.dataGrid.Items [ 0 ] );
}
else if ( e.Key == Key.F12 )
{
this.ViewScale += 0.1m;
}
}
void MainWindow_KeyDown ( object sender, KeyEventArgs e )
{
}
}
public class Coin
{
public string Symbol { get; set; }
public int PNL { get; set; }
public SolidColorBrush Color2 { get; set; }
public Coin ( string symbol, int pnl )
{
this.Symbol = symbol;
this.PNL = pnl;
Random rnd = new Random ( );
Color c = Color.FromRgb ( ( byte ) rnd.Next ( 256 ), ( byte ) rnd.Next ( 256 ), ( byte ) rnd.Next ( 256 ) );
this.Color2 = new SolidColorBrush ( c );
}
}
}
XAML:
<Window x:Class="test.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:test"
mc:Ignorable="d"
Name="myMainWindow"
SizeToContent="Width"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Title="Profit Tracker"
WindowStyle="None"
Topmost="True"
Height="426">
<Window.Resources>
<Style x:Key="DataGridColumnSeparatorStyle" TargetType="DataGridCell">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Rectangle VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Fill="#1e90ff"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="DataGridColumnAlarmStyle" TargetType="DataGridCell">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Rectangle VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Fill="#000000"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type DataGrid}">
<Setter Property="Background" Value="#FFF" />
<Setter Property="AlternationCount" Value="2" />
<Setter Property="BorderBrush" Value="Red" />
<Setter Property="BorderThickness" Value="0" />
</Style>
<Style x:Key="RowStyleWithAlternation" TargetType="DataGridRow">
<Setter Property="Background" Value="#141414"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="FontWeight" Value="Normal"/>
<Style.Triggers>
<Trigger Property="AlternationIndex" Value="0">
<Setter Property="Background" Value="#141414"/>
</Trigger>
<Trigger Property="AlternationIndex" Value="1">
<Setter Property="Background" Value="#282828"/>
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter Property="BorderBrush" Value="Red" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="Margin" Value="-1,0,0,0" />
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<!--<Setter Property="BorderBrush" Value="#2eff00" />
<Setter Property="BorderThickness" Value="1" />-->
<Setter Property="Background" Value="Orange"/>
<!--<Setter Property="Margin" Value="-1,0,0,0" />-->
</Trigger>
</Style.Triggers>
</Style>
<Style TargetType="DataGridCell">
<Setter Property="TextBlock.TextAlignment" Value="Center" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridCell}">
<Grid Background="{TemplateBinding Background}">
<ContentPresenter VerticalAlignment="Stretch"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="VerticalAlignment" Value="Stretch"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="Margin" Value="0"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="BorderBrush" Value="#1e90ff" />
<Setter Property="BorderThickness" Value="1" />
<!--<Setter Property="Background" Value="Red"/>-->
</Trigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Column.DisplayIndex, RelativeSource={RelativeSource Self}}" Value="4"/>
</MultiDataTrigger.Conditions>
<MultiDataTrigger.Setters>
<Setter Property="VerticalAlignment" Value="Stretch"/>
</MultiDataTrigger.Setters>
</MultiDataTrigger>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="{x:Null}"/>
<Setter Property="BorderBrush" Value="{x:Null}"/>
</Trigger>
</Style.Triggers>
</Style>
<Style TargetType="DataGridColumnHeader">
<Setter Property="HorizontalContentAlignment" Value="Center" />
</Style>
<Style TargetType="{x:Type ProgressBar}">
<Setter Property="Padding" Value="0"/>
<Setter Property="Margin" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ProgressBar">
<Border BorderThickness="1" Background="#006400" CornerRadius="0" Padding="0">
<Grid x:Name="PART_Track">
<Rectangle x:Name="PART_Indicator" HorizontalAlignment="Left" Fill="#75001D" />
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<CollectionViewSource Source="{Binding Coins}" IsLiveSortingRequested="True" x:Key="MyKey" />
</Window.Resources>
<Grid>
<Grid.LayoutTransform>
<ScaleTransform ScaleX="{Binding ViewScale, ElementName=myMainWindow}" ScaleY="{Binding ViewScale, ElementName=myMainWindow}" />
</Grid.LayoutTransform>
<DataGrid Name="dataGrid" ItemsSource="{Binding Source={StaticResource MyKey}}" SelectionMode="Single" GridLinesVisibility="None" HorizontalScrollBarVisibility="Hidden" RowHeaderWidth="0" IsReadOnly="True" CanUserAddRows="False" CanUserResizeColumns="False" CanUserResizeRows="False" AutoGenerateColumns="False" RowStyle="{StaticResource RowStyleWithAlternation}">
<DataGrid.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent" />
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Transparent" />
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTemplateColumn MinWidth="0" Width="2" CellStyle="{StaticResource DataGridColumnSeparatorStyle}"/>
<DataGridTextColumn Header="PNL" Width="60" SortMemberPath="Balance.UnitPrice" Binding="{Binding Path=PNL}" />
<DataGridTemplateColumn MinWidth="0" Width="2" CellStyle="{StaticResource DataGridColumnSeparatorStyle}" CanUserSort="False"/>
<DataGridTemplateColumn Header="Price" Width="60" SortMemberPath="Price">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Grid>
<Grid>
<Border BorderBrush="#241C59" BorderThickness="1" CornerRadius="1" Background="#2D255B">
<Border BorderBrush="#206fb6" BorderThickness="4" CornerRadius="2" ClipToBounds="True" Margin="-1" HorizontalAlignment="Stretch">
<Border.Effect>
<BlurEffect Radius="10"/>
</Border.Effect>
</Border>
</Border>
<Border Margin="1" VerticalAlignment="Stretch" BorderThickness="0." Background="#69ABDB" HorizontalAlignment="Left" Width="30">
<Border BorderBrush="#38e2ff" BorderThickness="2" CornerRadius="2" ClipToBounds="False">
<Border.Effect>
<BlurEffect Radius="5"/>
</Border.Effect>
</Border>
</Border>
</Grid>
<TextBlock Text="25%" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Vol BTC/h" Width="30" SortMemberPath="LastHourVolumeInBtc">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Grid>
<TextBlock Text="ABCDE" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Vol BTC/h" Width="40">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Grid>
<ProgressBar Value="0.3" Minimum="0" Maximum="1"/>
<TextBlock Text="12345" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="Net BTC/m" Width="60"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
In order to provide property changed notifications, you have to implement the INotifyPropertyChanged interface in the type that the bound property is defined. You missed this part in your MainWindow code-behind, which is also the data context of your window.
public partial class MainWindow : Window, INotifyPropertyChanged
Although you defined the PropertyChanged event and your SetField method raises the event correctly, WPF will not be aware of it, if you do not declare the interface on your class definition.
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.
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.
First of all I'm an amateur and non-english native speaker, so I would appreciate it if you would have a little patience with me ;)
Following another stackoverflow question, I've done a TabControl that expands itself (like an expander) just modifying the template of the original TabControl, so I can just alter the height of the control when any tab is selected.
That worked perfect, but needed some ViewModel properties for the logic. Now i need to use that control again and i thought the better way would be to make a CustomControl.
The problem I'm having is that the CustomControl are just lookless, no style are applied to it although I have specified styles for it in the Generic.xaml file, and the Build Action property to Page, revised the AsemblyInfo.cs, and used the DefaultStyleKeyProperty.OverrideMetadata in the static constructor. All following other questions suggestions.
I think it'd be better to show the code I have now and then explain what more I've tried, I have to say that I was writing the logic when I noticed this, so it does not work right now.
Generic.xaml:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:PRUEBA_TABBEDEXPANDER"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
xmlns:ie="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:Core="clr-namespace:Microsoft.Expression.Interactivity.Core;assembly=Microsoft.Expression.Interactions"
xmlns:int="clr-namespace:System.Windows.Interactivity">
<SolidColorBrush x:Key="TabControlNormalBorderBrush" Color="#8C8E94"/>
<Style x:Key="TabItemFocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Rectangle Margin="3,3,3,1" SnapsToDevicePixels="true" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" StrokeThickness="1" StrokeDashArray="1 2"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<LinearGradientBrush x:Key="ButtonNormalBackground" EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="#F3F3F3" Offset="0"/>
<GradientStop Color="#EBEBEB" Offset="0.5"/>
<GradientStop Color="#DDDDDD" Offset="0.5"/>
<GradientStop Color="#CDCDCD" Offset="1"/>
</LinearGradientBrush>
<LinearGradientBrush x:Key="TabItemHotBackground" EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="#EAF6FD" Offset="0.15"/>
<GradientStop Color="#D9F0FC" Offset=".5"/>
<GradientStop Color="#BEE6FD" Offset=".5"/>
<GradientStop Color="#A7D9F5" Offset="1"/>
</LinearGradientBrush>
<SolidColorBrush x:Key="TabItemSelectedBackground" Color="#F9F9F9"/>
<SolidColorBrush x:Key="TabItemHotBorderBrush" Color="#3C7FB1"/>
<SolidColorBrush x:Key="TabItemDisabledBackground" Color="#F4F4F4"/>
<SolidColorBrush x:Key="TabItemDisabledBorderBrush" Color="#FFC9C7BA"/>
<Style x:Key="TabItemStyle1" TargetType="{x:Type TabItem}">
<Setter Property="FocusVisualStyle" Value="{StaticResource TabItemFocusVisual}"/>
<Setter Property="Foreground" Value="Black"/>
<Setter Property="Padding" Value="6,1,6,1"/>
<Setter Property="BorderBrush" Value="{StaticResource TabControlNormalBorderBrush}"/>
<Setter Property="Background" Value="{StaticResource ButtonNormalBackground}"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid SnapsToDevicePixels="true">
<Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="1,1,1,0" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}">
<ToggleButton x:Name="Content" Content="{TemplateBinding Header}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<ei:CallMethodAction MethodName="ToggleButton_Click"
TargetObject="{Binding RelativeSource={RelativeSource TemplatedParent}}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ToggleButton>
<!--<ContentPresenter x:Name="Content" ContentSource="Header"
HorizontalAlignment="{Binding HorizontalContentAlignment,
RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"
RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
VerticalAlignment="{Binding VerticalContentAlignment,
RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>-->
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Background" TargetName="Bd" Value="{StaticResource TabItemHotBackground}"/>
</Trigger>
<Trigger Property="IsSelected" Value="true">
<Setter Property="Panel.ZIndex" Value="1"/>
<Setter Property="Background" TargetName="Bd" Value="{StaticResource TabItemSelectedBackground}"/>
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="false"/>
<Condition Property="IsMouseOver" Value="true"/>
</MultiTrigger.Conditions>
<Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource TabItemHotBorderBrush}"/>
</MultiTrigger>
<Trigger Property="TabStripPlacement" Value="Bottom">
<Setter Property="BorderThickness" TargetName="Bd" Value="1,0,1,1"/>
</Trigger>
<Trigger Property="TabStripPlacement" Value="Left">
<Setter Property="BorderThickness" TargetName="Bd" Value="1,1,0,1"/>
</Trigger>
<Trigger Property="TabStripPlacement" Value="Right">
<Setter Property="BorderThickness" TargetName="Bd" Value="0,1,1,1"/>
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="true"/>
<Condition Property="TabStripPlacement" Value="Top"/>
</MultiTrigger.Conditions>
<Setter Property="Margin" Value="-2,-2,-2,-1"/>
<Setter Property="Margin" TargetName="Content" Value="0,0,0,1"/>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="true"/>
<Condition Property="TabStripPlacement" Value="Bottom"/>
</MultiTrigger.Conditions>
<Setter Property="Margin" Value="-2,-1,-2,-2"/>
<Setter Property="Margin" TargetName="Content" Value="0,1,0,0"/>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="true"/>
<Condition Property="TabStripPlacement" Value="Left"/>
</MultiTrigger.Conditions>
<Setter Property="Margin" Value="-2,-2,-1,-2"/>
<Setter Property="Margin" TargetName="Content" Value="0,0,1,0"/>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="true"/>
<Condition Property="TabStripPlacement" Value="Right"/>
</MultiTrigger.Conditions>
<Setter Property="Margin" Value="-1,-2,-2,-2"/>
<Setter Property="Margin" TargetName="Content" Value="1,0,0,0"/>
</MultiTrigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Background" TargetName="Bd" Value="{StaticResource TabItemDisabledBackground}"/>
<Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource TabItemDisabledBorderBrush}"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="TabbedExpanderTabControlStyle" TargetType="{x:Type TabControl}">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="Padding" Value="4,4,4,4"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="BorderBrush" Value="{StaticResource TabControlNormalBorderBrush}"/>
<Setter Property="Background" Value="#F9F9F9"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="ItemContainerStyle" Value="{StaticResource TabItemStyle1}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabControl}">
<Grid ClipToBounds="true" SnapsToDevicePixels="true" KeyboardNavigation.TabNavigation="Local">
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="ColumnDefinition0"/>
<ColumnDefinition x:Name="ColumnDefinition1" Width="0"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition x:Name="RowDefinition0" Height="Auto"/>
<RowDefinition x:Name="RowDefinition1" Height="*"/>
</Grid.RowDefinitions>
<TabPanel x:Name="HeaderPanel" Grid.Column="0" IsItemsHost="true" Margin="2,2,2,0" Grid.Row="0" KeyboardNavigation.TabIndex="1" Panel.ZIndex="1"/>
<Border x:Name="ContentPanel" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Grid.Column="0" KeyboardNavigation.DirectionalNavigation="Contained" Grid.Row="1" KeyboardNavigation.TabIndex="2" KeyboardNavigation.TabNavigation="Local">
<ContentPresenter x:Name="PART_SelectedContentHost" ContentSource="SelectedContent" Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="TabStripPlacement" Value="Bottom">
<Setter Property="Grid.Row" TargetName="HeaderPanel" Value="1"/>
<Setter Property="Grid.Row" TargetName="ContentPanel" Value="0"/>
<Setter Property="Height" TargetName="RowDefinition0" Value="*"/>
<Setter Property="Height" TargetName="RowDefinition1" Value="Auto"/>
<Setter Property="Margin" TargetName="HeaderPanel" Value="2,0,2,2"/>
</Trigger>
<Trigger Property="TabStripPlacement" Value="Left">
<Setter Property="Grid.Row" TargetName="HeaderPanel" Value="0"/>
<Setter Property="Grid.Row" TargetName="ContentPanel" Value="0"/>
<Setter Property="Grid.Column" TargetName="HeaderPanel" Value="0"/>
<Setter Property="Grid.Column" TargetName="ContentPanel" Value="1"/>
<Setter Property="Width" TargetName="ColumnDefinition0" Value="Auto"/>
<Setter Property="Width" TargetName="ColumnDefinition1" Value="*"/>
<Setter Property="Height" TargetName="RowDefinition0" Value="*"/>
<Setter Property="Height" TargetName="RowDefinition1" Value="0"/>
<Setter Property="Margin" TargetName="HeaderPanel" Value="2,2,0,2"/>
</Trigger>
<Trigger Property="TabStripPlacement" Value="Right">
<Setter Property="Grid.Row" TargetName="HeaderPanel" Value="0"/>
<Setter Property="Grid.Row" TargetName="ContentPanel" Value="0"/>
<Setter Property="Grid.Column" TargetName="HeaderPanel" Value="1"/>
<Setter Property="Grid.Column" TargetName="ContentPanel" Value="0"/>
<Setter Property="Width" TargetName="ColumnDefinition0" Value="*"/>
<Setter Property="Width" TargetName="ColumnDefinition1" Value="Auto"/>
<Setter Property="Height" TargetName="RowDefinition0" Value="*"/>
<Setter Property="Height" TargetName="RowDefinition1" Value="0"/>
<Setter Property="Margin" TargetName="HeaderPanel" Value="0,2,2,2"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="TabbedExpanderStyle" TargetType="{x:Type local:TabbedExpander}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:TabbedExpander}">
<Grid>
<TabControl Style="{StaticResource TabbedExpanderTabControlStyle}"></TabControl>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
TabbedExpander.cs:
public class TabbedExpander : TabControl, INotifyPropertyChanged
{
static TabbedExpander()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(TabbedExpander), new FrameworkPropertyMetadata(typeof(TabbedExpander)));
}
#region dependency properties
public ObservableCollection<object> ItemsS
{
get { return (ObservableCollection<object>)GetValue(ItemsSProperty); }
set { SetValue(ItemsSProperty, value); }
}
// Using a DependencyProperty as the backing store for ItemsS. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ItemsSProperty =
DependencyProperty.Register("ItemsS", typeof(ObservableCollection<object>), typeof(TabbedExpander),
new PropertyMetadata(new ObservableCollection<object>(), OnItemsSPropertyChanged));
private static void OnItemsSPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
TabbedExpander control = d as TabbedExpander;
var old = e.OldValue as ObservableCollection<object>;
if (old != null)
{
// Unsubscribe from CollectionChanged on the old collection
old.CollectionChanged -= control.ItemsSCollectionChanged;
}
var n = e.NewValue as ObservableCollection<object>;
if (n != null)
{
// Subscribe to CollectionChanged on the new collection
n.CollectionChanged += control.ItemsSCollectionChanged;
}
}
private void ItemsSCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Reset) base.Items.Clear();
if (e.NewItems != null)
{
foreach (object item in e.NewItems)
{
base.Items.Add(item);
}
}
if (e.OldItems != null)
{
foreach (object item in e.OldItems)
{
base.Items.RemoveAt(e.OldStartingIndex);
}
}
}
#region public
public bool IsExpanded
{
get { return (bool)GetValue(IsExpandedProperty); }
set { SetValue(IsExpandedProperty, value); }
}
public double EXPANDER_OFFSET
{
get { return (double)GetValue(EXPANDER_OFFSETProperty); }
set { SetValue(EXPANDER_OFFSETProperty, value); }
}
public int EXPANDER_MIN_HEIGHT
{
get { return (int)GetValue(EXPANDER_MIN_HEIGHTProperty); }
set { SetValue(EXPANDER_MIN_HEIGHTProperty, value); }
}
public int EXPANDER_MAX_HEIGHT
{
get { return (int)GetValue(EXPANDER_MAX_HEIGHTProperty); }
set { SetValue(EXPANDER_MAX_HEIGHTProperty, value); }
}
public int EXPANDER_NOTEXPANDED_HEIGHT
{
get { return (int)GetValue(EXPANDER_NOTEXPANDED_HEIGHTProperty); }
set { SetValue(EXPANDER_NOTEXPANDED_HEIGHTProperty, value); }
}
public double EXPANDER_EXPANDED_HEIGHT
{
get { return (double)GetValue(EXPANDER_EXPANDED_HEIGHTProperty); }
set { SetValue(EXPANDER_EXPANDED_HEIGHTProperty, value); }
}
#endregion
#region static
public static readonly DependencyProperty IsExpandedProperty =
DependencyProperty.Register("IsExpanded",
typeof(bool),
typeof(TabbedExpander),
new PropertyMetadata(false, OnIsExpandedChanged));
private static void OnIsExpandedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
TabbedExpander control = d as TabbedExpander;
if ((bool)e.NewValue) control.Height = control.EXPANDER_EXPANDED_HEIGHT;
else control.Height = control.EXPANDER_NOTEXPANDED_HEIGHT;
}
public static readonly DependencyProperty EXPANDER_OFFSETProperty =
DependencyProperty.Register("EXPANDER_OFFSET",
typeof(double),
typeof(TabbedExpander),
new PropertyMetadata(102d, OnOffsetChanged));
private static void OnOffsetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
throw new NotImplementedException();
}
public static readonly DependencyProperty EXPANDER_MIN_HEIGHTProperty =
DependencyProperty.Register("EXPANDER_MIN_HEIGHT",
typeof(int),
typeof(TabbedExpander),
new PropertyMetadata(96, OnMinHeightChanged));
private static void OnMinHeightChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
throw new NotImplementedException();
}
public static readonly DependencyProperty EXPANDER_MAX_HEIGHTProperty =
DependencyProperty.Register("EXPANDER_MAX_HEIGHT",
typeof(int),
typeof(TabbedExpander),
new PropertyMetadata(400, OnMaxHeightChanged));
private static void OnMaxHeightChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
throw new NotImplementedException();
}
public static readonly DependencyProperty EXPANDER_NOTEXPANDED_HEIGHTProperty =
DependencyProperty.Register("EXPANDER_NOTEXPANDED_HEIGHT",
typeof(int),
typeof(TabbedExpander),
new PropertyMetadata(30, OnNotExpandedHeightChanged));
private static void OnNotExpandedHeightChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
throw new NotImplementedException();
}
public static readonly DependencyProperty EXPANDER_EXPANDED_HEIGHTProperty =
DependencyProperty.Register("EXPANDER_EXPANDED_HEIGHT",
typeof(double),
typeof(TabbedExpander),
new PropertyMetadata(100d, OnExpandedHeightChanged));
private static void OnExpandedHeightChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
throw new NotImplementedException();
}
#endregion
#endregion
#region PropertyChanged
public event PropertyChangedEventHandler PropertyChanged = delegate { };
protected void NotifyPropChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
this.Height = this.EXPANDER_NOTEXPANDED_HEIGHT;
}
}
And a little MainWindow.xaml for testing:
<Window x:Class="PRUEBA_TABBEDEXPANDER.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:PRUEBA_TABBEDEXPANDER"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<local:TabbedExpander TabStripPlacement="Top">
<TabItem Header="prueba1">
<TextBox Text="prueba1"/>
</TabItem>
</local:TabbedExpander>
</Grid>
That's my last try, my first try was to apply the TabbedExpanderTabControlStyle style directly to the custom control just changing the TargetType, then i've tried without adding the ItemsSProperty, just using the TabControl's inherited ItemsSource with the same syntax in the 'MainWindow.xaml`, and changing the syntax to:
<Grid>
<local:TabbedExpander TabStripPlacement="Top">
<local:TabbedExpander.ItemsS>
<TabItem Header="prueba1">
<TextBox Text="prueba1"/>
</TabItem>
</local:TabbedExpander.ItemsS>
</local:TabbedExpander>
</Grid>
As well as <local:TabbedExpander.Items> trying to use the TabControl's inherited Items.
The only thing that worked was to merge the Generic.xaml as a ResourceDictionary and apply TabbedExpanderTabControlStyle directly to the custom control... which I suppose is NOT the correct way to do it... right? Because i would have to apply the style to every custom control I would add to my application...
I suppose that either I'm doing something wrong applying the style, or using the tabitems collections, but right now I'm out of ideas :(
Any idea?
Normally you'd add your generic style to your window (or other high-level control) resource dictionary like this:
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Themes/Generic.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
So that all child controls will inherit it. Have you tried that?
Note, now you've created a custom control you'll want to change the target type of your style and it will apply to all instances of your control in your application. (though looks like you've already thought of that)
If you are using this control elsewhere it might be worth having the style in it's own file, then other projects can include it in their own generic/windows resource directories. This is how wellknown libraries like MahhApps.Metro work, for example with their controls my generic.xaml might look like this:
<ResourceDictionary ...>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
... other imported resource dictionaries
</ResourceDictionary.MergedDictionaries>
...my application specific stuff...
</ResourceDictionary>
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>