TabControl inherited CustomControl doesn't show anything - c#

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>

Related

Why does the content disappear after adding a border to the DataGrid (WPF C#)

I added round corner border to DataGrid:
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGrid}">
<Border Background="Transparent" CornerRadius="5" BorderBrush="{DynamicResource HiGrayBrush}" BorderThickness="1,2,1,2" SnapsToDevicePixels="True"/>
</ControlTemplate>
</Setter.Value>
</Setter>
After border added, the content disappers
Before:
After:
Xaml:
<Grid>
<Viewbox Stretch="Fill">
<Canvas Height="900" Width="1000">
<DataGrid x:Name="mDataGrid" Canvas.Left="20" Canvas.Top="34" Height="530" Width="510"
LoadingRow="DataGrid_LoadingRow">
<DataGrid.RowHeaderTemplate>
<DataTemplate>
<Label HorizontalContentAlignment="Left"
Content="{Binding RelativeSource={RelativeSource AncestorType=DataGridRow},Path=Header}"/>
</DataTemplate>
</DataGrid.RowHeaderTemplate>
</DataGrid>
</Canvas>
</Viewbox>
</Grid>
Style:
<Style x:Key="CellTextBoxStyle" TargetType="TextBox">
<Setter Property="Width" Value="25"/>
<Setter Property="Height" Value="25"/>
<Setter Property="MaxLength" Value="2"/>
<Setter Property="Foreground" Value="{DynamicResource HiBlackBrush}" />
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
</Style>
<Style x:Key="DataGridHeadStyle" TargetType="DataGridColumnHeader">
<Setter Property="Width" Value="30"/>
<Setter Property="Height" Value="30"/>
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderThickness" Value="1,0,0,1"/>
<Setter Property="BorderBrush" Value="{DynamicResource HiGrayBrush}"/>
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="Margin" Value="-1,0,0,-1"/>
</Style>
<Style x:Key="DataGridRowHeadStyle" TargetType="DataGridRowHeader">
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderThickness" Value="0,0,1,1"/>
<Setter Property="BorderBrush" Value="{DynamicResource HiGrayBrush}"/>
<Setter Property="Foreground" Value="{DynamicResource HiBlackBrush}" />
<Setter Property="Padding" Value="5,0,0,0"/>
</Style>
<Style x:Key="DataGridCellStyle" TargetType="DataGridCell">
<Setter Property="Width" Value="30"/>
<Setter Property="Height" Value="30"/>
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderThickness" Value="1,0,0,1"/>
<Setter Property="BorderBrush" Value="{DynamicResource HiGrayBrush}"/>
<Setter Property="Foreground" Value="{DynamicResource HiBlackBrush}" />
<Setter Property="Margin" Value="-1,0,0,0"/>
</Style>
<Style x:Key="FirstDataGridCellStyle" TargetType="DataGridCell">
<Setter Property="Width" Value="30"/>
<Setter Property="Height" Value="30"/>
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderThickness" Value="0,0,0,1"/>
<Setter Property="BorderBrush" Value="{DynamicResource HiGrayBrush}"/>
<Setter Property="Foreground" Value="{DynamicResource HiBlackBrush}" />
<Setter Property="Margin" Value="-1,0,0,0"/>
</Style>
<Style x:Key="DataGridStyle" TargetType="DataGrid">
<Setter Property="CanUserReorderColumns" Value="False"/>
<Setter Property="CanUserResizeColumns" Value="False"/>
<Setter Property="CanUserSortColumns" Value="False"/>
<Setter Property="CanUserDeleteRows" Value="False"/>
<Setter Property="CanUserAddRows" Value="False"/>
<Setter Property="AutoGenerateColumns" Value="False"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="HorizontalGridLinesBrush" Value="{DynamicResource HiGrayBrush}"/>
<Setter Property="VerticalGridLinesBrush" Value="{DynamicResource HiGrayBrush}"/>
<Setter Property="VerticalScrollBarVisibility" Value="Disabled"/>
<Setter Property="HorizontalScrollBarVisibility" Value="Disabled"/>
<Setter Property="RowHeight" Value="30"/>
<Setter Property="RowHeaderWidth" Value="30"/>
<Setter Property="GridLinesVisibility" Value="None"/>
<Setter Property="SelectionMode" Value="Single"/>
<Setter Property="ScrollViewer.CanContentScroll" Value="False"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGrid}">
<Border Background="Transparent" CornerRadius="5" BorderBrush="{DynamicResource HiGrayBrush}" BorderThickness="1,2,1,2" SnapsToDevicePixels="True"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
C#:
private void initDataGrid()
{
mDataGrid.SetValue(DataGrid.StyleProperty, Application.Current.FindResource("DataGridStyle"));
mDataGridList = new List<RegisterValue>();
for (int i = 0; i < MAX; i++)
{
mDataGridList.Add(new RegisterValue()
{
mId = i.ToString("X01"),
Data0 = i.ToString("X02"),
Data1 = (i + 1).ToString("X02"),
Data2 = (i + 2).ToString("X02"),
Data3 = (i + 3).ToString("X02"),
Data4 = (i + 4).ToString("X02"),
Data5 = (i + 5).ToString("X02"),
Data6 = (i + 6).ToString("X02"),
Data7 = (i + 7).ToString("X02"),
Data8 = (i + 8).ToString("X02"),
Data9 = (i + 9).ToString("X02"),
Data10 = (i + 10).ToString("X02"),
Data11 = (i + 11).ToString("X02"),
Data12 = (i + 12).ToString("X02"),
Data13 = (i + 13).ToString("X02"),
Data14 = (i + 14).ToString("X02"),
Data15 = (i + 15).ToString("X02"),
});
DataGridTemplateColumn column = new DataGridTemplateColumn();
column.Header = Convert.ToUInt32(i).ToString("X01");
FrameworkElementFactory tempTextBox = new FrameworkElementFactory(typeof(TextBox));
tempTextBox.SetBinding(TextBox.TextProperty, new Binding("Data" + i));
tempTextBox.SetValue(TextBox.StyleProperty, Application.Current.FindResource("CellTextBoxStyle"));
DataTemplate dataTemplate = new DataTemplate();
dataTemplate.VisualTree = tempTextBox;
column.CellTemplate = dataTemplate;
column.SetValue(DataGridTemplateColumn.HeaderStyleProperty, Application.Current.FindResource("DataGridHeadStyle"));
column.SetValue(DataGridTemplateColumn.WidthProperty, new DataGridLength(1, DataGridLengthUnitType.Star));
if (i > 0)
{
column.SetValue(DataGridTemplateColumn.CellStyleProperty, Application.Current.FindResource("DataGridCellStyle"));
}
else
{
column.SetValue(DataGridTemplateColumn.CellStyleProperty, Application.Current.FindResource("FirstDataGridCellStyle"));
}
mDataGrid.Columns.Add(column);
}
mDataGrid.SetValue(DataGrid.RowHeaderStyleProperty, Application.Current.FindResource("DataGridRowHeadStyle"));
mDataGrid.ItemsSource = mDataGridList;
}
How can I add the border properly?

wpf - A multistage button

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>

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.

default style of custom control in wpf

i want to design a flexible imagebutton in wpf.
first,i create a WPF Custom Control Library in nameSpace 'ImageButton' like below:
namespace ImageButton
{
public class ImageButton : Button
{
static ImageButton()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(ImageButton), new FrameworkPropertyMetadata(typeof(ImageButton)));
}
#region DisplayMode
[System.ComponentModel.Category("ImageButton")]
public ImageDisplayMode DisplayMode
{
get { return (ImageDisplayMode)GetValue(DisplayModeProperty); }
set { SetValue(DisplayModeProperty, value); }
}
public static readonly DependencyProperty DisplayModeProperty =
DependencyProperty.Register("DisplayMode", typeof(ImageDisplayMode), typeof(ImageButton), new FrameworkPropertyMetadata(ImageDisplayMode.ImageAboveText), displaymodevalidate);
public static bool displaymodevalidate(object value)
{
return value is ImageDisplayMode;
}
#endregion
}
}
in the namespace "ImageButton" i define a enum named 'ImageDisplayMode' like below:
public enum ImageDisplayMode
{
ImageAboveText = 1,
TextAboveImage = 2,
ImageBeforeText = 3,
TextBeforeImage = 4
}
and the Generic.xaml file modified like below:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ImageButton">
<Style x:Name="style1" TargetType="{x:Type local:ImageButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:ImageButton}">
<Button Background="Transparent">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Image Grid.ColumnSpan="2" Name="img1" Width="{TemplateBinding ImageWidth}" Stretch="{TemplateBinding ImageStretch}" Height="{TemplateBinding ImageHeight}" Source="{TemplateBinding Image}"/>
<TextBlock Grid.ColumnSpan="2" Grid.Row="1" Name="lbl1" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Text="{TemplateBinding Text}"/>
</Grid>
</Button>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
the result of above code is below figure:
[Image]
Text
i want:
when i change the value of 'DisplayMode' property of imagebutton,for each possible value ,control changes to below forms:
1-------------------------------------
[Image]
Text
2-------------------------------------
Text
[Image]
3-------------------------------------
[Image]Text
4--------------------------------------
Text[Image]
i guess ,i must define trigger in the grid in Generic.xaml codes like below:
<Grid.Triggers>
<Trigger Property="DisplayMode" Value="2">
<Setter Property="Grid.Row" TargetName="lbl1" Value="0"/>
<Setter Property="Grid.Row" TargetName="img1" Value="1"/>
</Trigger>
</Grid.Triggers>
please tell me :
How can i do it?
Thank you Very Much
Add the triggers to your style (i.e. <Style.Triggers>...</Style.Triggers>).
I.e. something like this:
<Style.Triggers>
<Trigger Property="DisplayMode" Value="2">
<Setter Property="Grid.Row" TargetName="lbl1" Value="0"/>
<Setter Property="Grid.Row" TargetName="img1" Value="1"/>
</Trigger>
</Style.Triggers>
thanks fmunkert ...
I move my triggers to ControlTemplate.Triggers and change Trigger.Value from "2" to "ImageAboveText" ( one of my custom enum items ) like below:
Before Edit:
<Trigger Property="DisplayMode" Value="2">
<Setter Property="Grid.Row" TargetName="lbl1" Value="0"/>
<Setter Property="Grid.Row" TargetName="img1" Value="1"/>
</Trigger>
After Edit:
<Trigger Property="DisplayMode" Value="ImageAboveText">
<Setter Property="Grid.Row" TargetName="lbl1" Value="0"/>
<Setter Property="Grid.Row" TargetName="img1" Value="1"/>
</Trigger>
my problem solved successfully....
Thank you.

Categories

Resources