This is my combo-box.
<ComboBox Height="45" HorizontalAlignment="Left" Margin="184,66,0,0" Name="ComboBox1" VerticalAlignment="Top" Width="216">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Label Content="{Binding FullName}" Width="150" />
<Label Content="{Binding Title}" Width="100"/>
<Label Content="{Binding BranchName}" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
How can I change it so that only the FullName appears in the textbox portion of the combobox while all three columns still appear in the drop-down portion?
Unfortunately, the SelectionBoxItemTemplate is a readonly property, so we have to do a bit more work. By doing the ItemTemplate to be how you want the item to appear when selected, you can edit the ItemContainerStyle to provide a ControlTemplate that includes the other fields you want to display.
<ComboBox Height="45" HorizontalAlignment="Left" Margin="184,66,0,0" Name="ComboBox1" VerticalAlignment="Top" Width="216">
<ComboBox.ItemTemplate>
<DataTemplate>
<Label Content="{Binding FullName}" Width="150" />
</DataTemplate>
</ComboBox.ItemTemplate>
<ComboBox.ItemContainerStyle>
<Style TargetType="{x:Type ComboBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ComboBoxItem}">
<Border x:Name="Bd"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}">
<StackPanel Orientation="Horizontal">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
<Label Content="{Binding Title}" Width="100"/>
<Label Content="{Binding BranchName}" />
</StackPanel>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsHighlighted" Value="True">
<Setter TargetName="Bd" Property="Background" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" />
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ComboBox.ItemContainerStyle>
</ComboBox>
For the ComboBoxItem template, I just modified the default one, so it should be fully functional.
If the ComboBox's IsEditable property is set to True, you can set the "TextSearch.TextPath" property of the ComboBox to the property name you want to show. So in your case:
<ComboBox IsEditable="True" TextSearch.TextPath="FullName" .../>
Instead of using the read-only SelectionBoxItemTemplate property I created a new (attached, writable) property and used that one in my style. I also added a trigger to my style to not break all the comboboxes that are not using my new attached property...
Use it like this:
<ComboBox ItemsSource="{Binding ...}" SelectedItem="{Binding ..., Mode=TwoWay}">
<controls:ComboBoxSelectionBoxAltTemplateBehaviour.SelectionBoxAltTemplate>
<DataTemplate DataType="{x:Type ...}">
... Template for the selection box ...
</DataTemplate>
</controls:ComboBoxSelectionBoxAltTemplateBehaviour.SelectionBoxAltTemplate>
<ComboBox.ItemTemplate>
<DataTemplate DataType="{x:Type ...}">
... Template for the popup ...
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
You just have to add this class to your project:
public class ComboBoxSelectionBoxAltTemplateBehaviour
{
public static readonly DependencyProperty SelectionBoxAltTemplateProperty = DependencyProperty.RegisterAttached(
"SelectionBoxAltTemplate", typeof (DataTemplate), typeof (ComboBoxSelectionBoxAltTemplateBehaviour), new PropertyMetadata(default(DataTemplate)));
public static void SetSelectionBoxAltTemplate(DependencyObject element, DataTemplate value)
{
element.SetValue(SelectionBoxAltTemplateProperty, value);
}
public static DataTemplate GetSelectionBoxAltTemplate(DependencyObject element)
{
return (DataTemplate) element.GetValue(SelectionBoxAltTemplateProperty);
}
}
and change your ComboBox style to use the SelectionBoxAltTemplate attached property if set (or because I could not set a trigger to "not null", I set it back to the default SelectionBoxItemTemplate if the attached one is null):
The ContentPresenter inside the ControlTemplate of the ComboBox Style:
<ContentPresenter Content="{TemplateBinding SelectionBoxItem}" ContentTemplate="{TemplateBinding controls:ComboBoxSelectionBoxAltTemplateBehaviour.SelectionBoxAltTemplate}" />
And the Trigger to provide backwards compatibility to ComboBoxed without the attached Property:
<ControlTemplate.Triggers>
<Trigger Property="controls:ComboBoxSelectionBoxAltTemplateBehaviour.SelectionBoxAltTemplate" Value="{x:Null}">
<Setter Property="ContentTemplate" Value="{Binding SelectionBoxItemTemplate, RelativeSource={RelativeSource TemplatedParent}}" TargetName="ContentSite" />
</Trigger>
...
</ControlTemplate.Triggers>
Full Style:
<Style x:Key="{x:Type ComboBox}" TargetType="{x:Type ComboBox}">
<Setter Property="SnapsToDevicePixels" Value="true" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="FontSize" Value="12" />
<Setter Property="Background" Value="{StaticResource ComboBoxBackground}"/>
<Setter Property="BorderBrush" Value="{StaticResource ComboBoxBorder}"/>
<Setter Property="Margin" Value="6"/>
<Setter Property="Padding" Value="3,3,5,3"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ComboBox}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Border Name="Border" Grid.ColumnSpan="2" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"/>
<ToggleButton Name="ToggleButton2" Focusable="False" IsChecked="{Binding Path=IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" ClickMode="Press" Grid.ColumnSpan="2" Background="Transparent"/>
<!-- Allows clicking anywhere on the combobox, not only the visible button on the right -->
<ToggleButton Focusable="false" Grid.Column="1" x:Name="ToggleButton" IsChecked="{Binding Path=IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" ClickMode="Press" Style="{StaticResource ComboBoxToggleButton}"/>
<ContentPresenter HorizontalAlignment="Left" Margin="{TemplateBinding Control.Padding}" x:Name="ContentSite" VerticalAlignment="Center" Content="{TemplateBinding SelectionBoxItem}" ContentTemplate="{TemplateBinding controls:ComboBoxSelectionBoxAltTemplateBehaviour.SelectionBoxAltTemplate}" ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}" IsHitTestVisible="False" />
<TextBox Visibility="Hidden" HorizontalAlignment="Left" Margin="{TemplateBinding Control.Padding}" x:Name="PART_EditableTextBox" Style="{x:Null}" VerticalAlignment="Center" Focusable="True" Background="Transparent" />
<Popup IsOpen="{TemplateBinding IsDropDownOpen}" Placement="Bottom" x:Name="Popup" Focusable="False" AllowsTransparency="True" PopupAnimation="Slide">
<Grid MaxHeight="{TemplateBinding MaxDropDownHeight}" MinWidth="{TemplateBinding ActualWidth}" x:Name="DropDown" SnapsToDevicePixels="True">
<Border x:Name="DropDownBorder" Background="{StaticResource ComboBoxBackground}" BorderBrush="{StaticResource ComboBoxBorder}" BorderThickness="1" Padding="0,4">
<ScrollViewer SnapsToDevicePixels="True" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" CanContentScroll="True" Style="{x:Null}" >
<StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Contained"/>
</ScrollViewer>
</Border>
</Grid>
</Popup>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="controls:ComboBoxSelectionBoxAltTemplateBehaviour.SelectionBoxAltTemplate" Value="{x:Null}">
<Setter Property="ContentTemplate" Value="{Binding SelectionBoxItemTemplate, RelativeSource={RelativeSource TemplatedParent}}" TargetName="ContentSite" />
</Trigger>
<Trigger Property="HasItems" Value="false">
<Setter Property="MinHeight" Value="95" TargetName="DropDownBorder" />
</Trigger>
<Trigger Property="IsGrouping" Value="true">
<Setter Property="ScrollViewer.CanContentScroll" Value="false" />
</Trigger>
<Trigger Property="IsEditable" Value="true">
<Setter Property="IsTabStop" Value="false" />
<Setter Property="Visibility" Value="Visible" TargetName="PART_EditableTextBox" />
<Setter Property="Visibility" Value="Hidden" TargetName="ContentSite" />
</Trigger>
<Trigger Property="IsMouseOver" Value="true" SourceName="ToggleButton2">
<Setter Property="Background" Value="{StaticResource ComboBoxMouseOver}" />
</Trigger>
<Trigger Property="HasItems" Value="False">
<Setter Property="IsEnabled" Value="False"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
However this might not work with ItemTemplateSelctors, only with one single template - but you could easily add an attached property "SelectionBoxAltTemplateSelector" which provides the selector and passes that one to the style.
There is a pretty good answer to your question here if you don't want to change the ComboBoxes style: https://stackoverflow.com/a/2277488/1070906
It uses a Trigger in the DataTemplate which looks if there is a ComboBoxItem somewhere above in the visual tree, which is not the case in the selection box.
You could override the ComboBox and change the SelectionBoxItemTemplate directly.
public class SelectionComboBox : ComboBox
{
#region Properties
#region Dependency Properties
public DataTemplate AltSelectionBoxItemTemplate
{
get { return (DataTemplate)GetValue(AltSelectionBoxItemTemplateProperty); }
set { SetValue(AltSelectionBoxItemTemplateProperty, value); }
}
public static readonly DependencyProperty AltSelectionBoxItemTemplateProperty =
DependencyProperty.Register("AltSelectionBoxItemTemplate", typeof(DataTemplate), typeof(SelectionComboBox), new UIPropertyMetadata(null, (s, e) =>
{
// For new changes...
if ((s is SelectionComboBox) && ((SelectionComboBox)s).Presenter != null && (e.NewValue is DataTemplate))
((SelectionComboBox)s).Presenter.ContentTemplate = (DataTemplate)e.NewValue;
// Set the new value
((SelectionComboBox)s).AltSelectionBoxItemTemplate = (DataTemplate)e.NewValue;
}));
#endregion
#region Internals
#region Elements
ContentPresenter Presenter { get; set; }
#endregion
#endregion
#endregion
#region Constructors
#endregion
#region Methods
#region Overrides
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
Presenter = this.GetTemplateChild("contentPresenter") as ContentPresenter;
// Directly Set the selected item template
if (AltSelectionBoxItemTemplate != null) Presenter.ContentTemplate = AltSelectionBoxItemTemplate;
}
#endregion
#endregion
}
Once you define the control, you could style it.
<controls:SelectionComboBox ItemsSource="{Binding ...}" SelectedItem="{Binding ..., Mode=TwoWay}">
<controls:SelectionComboBox.AltSelectionBoxItemTemplate>
<DataTemplate>
<!-- My Template Goes Here... -->
</DataTemplate>
</controls:SelectionComboBox.AltSelectionBoxItemTemplate>
</controls:SelectionComboBox>
Related
I have some textbox whith style from a template like this
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border Background="White" CornerRadius="8" x:Name="container">
<Grid>
<TextBox Background="White"
FontFamily="Poppins" FontSize="11"
VerticalAlignment="Center"
Padding="5"
Name="SearchBox"
Foreground="Black"
Margin="2"
BorderThickness="0"
Text="{TemplateBinding Text}"
/>
<TextBlock Text="{TemplateBinding Tag}" Name="Placeholder"
FontSize="11" FontFamily="Poppins"
Foreground="Gray"
VerticalAlignment="Center"
IsHitTestVisible="False"
Grid.Column="1" Padding="5" Margin="6,0,0,0">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding Text, ElementName=SearchBox}" Value="">
<Setter Property="Visibility" Value="Visible"></Setter>
</DataTrigger>
</Style.Triggers>
<Setter Property="Visibility" Value="Hidden"></Setter>
</Style>
</TextBlock.Style>
</TextBlock>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Background" Value="#E6E6E6" TargetName="container"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Just to show an placeholder. This works but something goes wrong when I try to bind property Text to a view model.
<TextBox Text="{Binding NombreCliente}"
Style="{StaticResource SearchTextBox}"
Grid.Row="1"
Tag="Nombre"/>
I've done test and while the textbox have this style the binding always return null or "".
I find in other ask that there's something whith binding parent and they solve whith this
<TextBox Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Text,
UpdateSourceTrigger=PropertyChanged}"....
But if i bind text to a template parent, how do I bind to viewmodel?
A template of a TextBox should not contain another TextBox control.
Replace it with a ScrollViewer and set the FontFamily and FontSize properties using Style setters:
<ControlTemplate TargetType="{x:Type TextBox}">
<Border Background="White" CornerRadius="8" x:Name="container">
<Grid>
<ScrollViewer x:Name="PART_ContentHost" Margin="2" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
<TextBlock Text="{TemplateBinding Tag}" Name="Placeholder"
FontSize="11" FontFamily="Poppins"
Foreground="Gray"
VerticalAlignment="Center"
IsHitTestVisible="False"
Grid.Column="1" Padding="5" Margin="6,0,0,0">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding Text, ElementName=SearchBox}" Value="">
<Setter Property="Visibility" Value="Visible"></Setter>
</DataTrigger>
</Style.Triggers>
<Setter Property="Visibility" Value="Hidden"></Setter>
</Style>
</TextBlock.Style>
</TextBlock>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Background" Value="#E6E6E6" TargetName="container"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
If this is a template for use in a TextBox, then you have created it incorrectly.
In fact, instead of giving the TextBox room to display the text, you have overlapped it on top with another TextBox that has nothing to do with the one this template will use.
TextBox to display text looks in its template for a ScrollViewer named PART_ContentHost.
And all the property settings of the TextBox must be moved to Setters outside the template.
Example template:
<Style TargetType="TextBox">
<Setter Property="Background" Value="White"/>
<Setter Property="FontFamily" Value="Poppins"/>
<Setter Property="FontSize" Value="11"/>
<Setter Property="Padding" Value="5"/>
<Setter Property="Foreground" Value="Black"/>
<Setter Property="Margin" Value="2"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border Background="{TemplateBinding Background}"
CornerRadius="8" x:Name="container"
Padding="{TemplateBinding Padding}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<ScrollViewer x:Name="PART_ContentHost"
Focusable="false"
HorizontalScrollBarVisibility="Hidden"
VerticalScrollBarVisibility="Hidden"/>
<TextBlock Text="{TemplateBinding Tag}" Name="Placeholder"
FontSize="11" FontFamily="Poppins"
Foreground="Gray"
VerticalAlignment="Center"
IsHitTestVisible="False"
Grid.Column="1" Padding="5" Margin="6,0,0,0">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding Text, ElementName=SearchBox}" Value="">
<Setter Property="Visibility" Value="Visible"></Setter>
</DataTrigger>
</Style.Triggers>
<Setter Property="Visibility" Value="Hidden"/>
</Style>
</TextBlock.Style>
</TextBlock>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Background" Value="#E6E6E6" TargetName="container"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The problem is IsMouseOver is not working when I hover the button, though I have customized the button and it is not working.
Can you say where is the error?
<cc:CustomFlatButton Grid.Column="1"
Margin="1,0,5,4"
Command="{Binding ElementName=me, Path=Command疑い}"
CommandParameter="{Binding}"
IsEnabled="{Binding Path=疑いIsEnableFlag}">
<Run FontWeight="Bold">
疑い病名
</Run>
<Button.Style>
<Style TargetType="cc:CustomFlatButton">
<Setter Property="MinWidth" Value="80" />
<Setter Property="FontFamily" Value="メイリオ" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type cc:CustomFlatButton}">
<Border Height="22"
Margin="1"
VerticalAlignment="Center"
Background="White"
BorderBrush="#FFFF5656"
BorderThickness="2"
CornerRadius="6"
RenderOptions.BitmapScalingMode="NearestNeighbor"
TextOptions.TextFormattingMode="Display"
UseLayoutRounding="True">
<Label Padding="0,1,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Content="{TemplateBinding Content}"
Foreground="Black" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="cc:CustomFlatButton.IsMouseOver" Value="True">
<Setter Property="Background" Value="DarkGoldenrod"/>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</cc:CustomFlatButton>
I have also checked if I use trigger Property="IsMouseOver". It is also not working. Where is the problem?
You have changed the Button Template and in this Template no property is bound to the Backgroud of the button.
In the trigger, you change the value of this property, but since no one uses this property, nothing changes in the display.
There are two main options to solve.
Set the Border's background binding to the Backgroud property of the button:
<cc:CustomFlatButton Grid.Column="1"
Margin="1,0,5,4"
Command="{Binding ElementName=me, Path=Command疑い}"
CommandParameter="{Binding}"
IsEnabled="{Binding Path=疑いIsEnableFlag}">
<Run FontWeight="Bold">
疑い病名
</Run>
<Button.Style>
<Style TargetType="cc:CustomFlatButton">
<Setter Property="MinWidth" Value="80" />
<Setter Property="FontFamily" Value="メイリオ" />
<Setter Property="Background" Value="White"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type cc:CustomFlatButton}">
<Border Height="22"
Margin="1"
VerticalAlignment="Center"
Background="{TemplateBinding Background}"
BorderBrush="#FFFF5656"
BorderThickness="2"
CornerRadius="6"
RenderOptions.BitmapScalingMode="NearestNeighbor"
TextOptions.TextFormattingMode="Display"
UseLayoutRounding="True">
<Label Padding="0,1,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Content="{TemplateBinding Content}"
Foreground="Black" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="cc:CustomFlatButton.IsMouseOver" Value="True">
<Setter Property="Background" Value="DarkGoldenrod"/>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</cc:CustomFlatButton>
Or change the Border background with ControlTemplate triggers.
But this is applicable if CustomFlatButton is a Custom Control and not a UserControl.
That is, the CustomFlatButton should not have any predefined XAML.
<cc:CustomFlatButton Grid.Column="1"
Margin="1,0,5,4"
Command="{Binding ElementName=me, Path=Command疑い}"
CommandParameter="{Binding}"
IsEnabled="{Binding Path=疑いIsEnableFlag}">
<Run FontWeight="Bold">
疑い病名
</Run>
<Button.Style>
<Style TargetType="cc:CustomFlatButton">
<Setter Property="MinWidth" Value="80" />
<Setter Property="FontFamily" Value="メイリオ" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type cc:CustomFlatButton}">
<Border x:Name="PART_Border"
Height="22"
Margin="1"
VerticalAlignment="Center"
Background="White"
BorderBrush="#FFFF5656"
BorderThickness="2"
CornerRadius="6"
RenderOptions.BitmapScalingMode="NearestNeighbor"
TextOptions.TextFormattingMode="Display"
UseLayoutRounding="True">
<Label Padding="0,1,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Content="{TemplateBinding Content}"
Foreground="Black" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="cc:CustomFlatButton.IsMouseOver" Value="True">
<Setter Property="Background" Value="DarkGoldenrod" TargetName="PART_Border"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Button.Style>
</cc:CustomFlatButton>
I have an Expander and it should receive the full width of the column but I cant get it to work.
I tried to add the Horizontal(Content)Alignment = stretch on the TextBlock and on the Expander itself even on the Grid, but it is not working.
What I need is that the Expander takes about 90% of the width and the rest are assigned to the buttons as in the following example:
I want to display e.g. a name and when you press on it, expands down and shows additional information
and if the buttons are pressed, then the commands behind the buttons will be executed (no commands are binded in the example).
<ListView
ItemsSource="{Binding log}"
SelectionMode="Multiple"
Style="{StaticResource ListViewStyle}">
<ListView.ItemTemplate>
<DataTemplate>
<Border BorderThickness="0,0,0,1" BorderBrush="Gray">
<Grid HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100*" />
<ColumnDefinition Width="5*" />
<ColumnDefinition Width="5*" />
</Grid.ColumnDefinitions>
<Expander Grid.Column="0"
HorizontalAlignment="Stretch"
IsExpanded="{Binding Mode=TwoWay, Path=IsSelected, RelativeSource={RelativeSource AncestorType=ListBoxItem, Mode=FindAncestor}}"
Style="{StaticResource ExpanderStyle}">
<Expander.Header>
<TextBlock Text="{Binding Name}" Foreground="White"
HorizontalAlignment="Stretch" />
</Expander.Header>
<TextBlock
VerticalAlignment="Center"
FontSize="16"
Foreground="White"
Text="{Binding Description}" />
</Expander>
<Button Grid.Column="1"
Style="{StaticResource IconButton}">
<Button.Background>
<ImageBrush ImageSource="../icons/edit.png"
Stretch="None" />
</Button.Background>
</Button>
<dialogButton:ConfirmButton Grid.Column="2"
Question="{x:Static language:Strings.confirm}"
Style="{DynamicResource IconButton}"
Margin="0,0,10,0">
<dialogButton:ConfirmButton.Background>
<ImageBrush ImageSource="../icons/delete.png"
Stretch="None" />
</dialogButton:ConfirmButton.Background>
</dialogButton:ConfirmButton>
</Grid>
</Border>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Styles
<Style x:Key="ExpanderDownHeaderStyle" TargetType="{x:Type ToggleButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Border Padding="{TemplateBinding Padding}">
<Grid Background="Transparent" SnapsToDevicePixels="False">
<ContentPresenter HorizontalAlignment="Stretch" Margin="0" RecognizesAccessKey="True" SnapsToDevicePixels="True" VerticalAlignment="Center"/>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ExpanderStyle" TargetType="{x:Type Expander}">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Expander}">
<Border Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}" CornerRadius="3" SnapsToDevicePixels="true">
<DockPanel>
<ToggleButton x:Name="HeaderSite" ContentTemplate="{TemplateBinding HeaderTemplate}" Content="{TemplateBinding Header}" ContentTemplateSelector="{TemplateBinding HeaderTemplateSelector}" DockPanel.Dock="Top" FontStyle="{TemplateBinding FontStyle}" FontStretch="{TemplateBinding FontStretch}" FontWeight="{TemplateBinding FontWeight}" FocusVisualStyle="{StaticResource ExpanderHeaderFocusVisual}" FontFamily="{TemplateBinding FontFamily}" Foreground="{TemplateBinding Foreground}" FontSize="{TemplateBinding FontSize}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" IsChecked="{Binding IsExpanded, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" MinHeight="0" MinWidth="0" Margin="1" Padding="{TemplateBinding Padding}" Style="{StaticResource ExpanderDownHeaderStyle}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
<ContentPresenter x:Name="ExpandSite" DockPanel.Dock="Bottom" Focusable="false" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Visibility="Collapsed"/>
</DockPanel>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsExpanded" Value="true">
<Setter Property="Visibility" TargetName="ExpandSite" Value="Visible"/>
</Trigger>
<Trigger Property="ExpandDirection" Value="Down">
<Setter Property="DockPanel.Dock" TargetName="ExpandSite" Value="Bottom"/>
<Setter Property="DockPanel.Dock" TargetName="HeaderSite" Value="Top"/>
<Setter Property="Background" Value="Transparent" />
<Setter Property="Style" TargetName="HeaderSite" Value="{StaticResource ExpanderDownHeaderStyle}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I also tried things from the following Threads
wpf - Header of Expander fit contents width?
Problem here is that the Buttons are pushed out of the view
Best Solution would be if the Expander just takes the width of the column so that I can adjust the widths of the element by the Grid.ColumnDefinition.
The issue is that the item container, a ListViewItem does not stretch its content by default. You have to create an item container style in order to set the HorizontalContentAlignment to Stretch.
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
</ListView.ItemContainerStyle>
So I have looked through numerous questions where people want to mess with borders of their buttons. I am using a toggle button (WPF) and it seems like there is an 'inner' border and an 'outer' border. I can manage to change the inner boarder to red, but I have no clue how to change the color of the outer border, or even get rid of it. I have gotten rid of the chrome button or whatever that comes with the aero theme, but I still cannot change this border. This is the picture of what I am getting for toggle buttons:
As you can see there is white in the borders. Here is my code for that style:
<Style x:Key="Style1" TargetType="{x:Type ToggleButton}">
<Setter Property="Background" Value="Black"/>
<Setter Property="BorderBrush" Value="Red"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Padding" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Button BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" SnapsToDevicePixels="true" Foreground="White">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Button>
<ControlTemplate.Triggers>
<Trigger Property="IsKeyboardFocused" Value="true">
</Trigger>
<Trigger Property="IsChecked" Value="true">
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="#ADADAD"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I am using it like this:
<ListBox SelectionMode="Single" Name="touchPanel" Grid.Row="2" Grid.Column="3" Width="Auto" Height="Auto" VerticalAlignment="Top" Background="Black" BorderThickness="0">
<RadioButton Width="60" Height="60" Name="mouseTouchSelection" IsChecked="True" Content="Mouse" Style="{DynamicResource RadioButtonStyle1}" />
<RadioButton Width="60" Height="60" Name="panTouchSelection" BorderThickness="0" Content="Pan" Style="{DynamicResource RadioButtonStyle1}" />
<RadioButton Width="60" Height="60" Name="rotateTouchSelection" Content="Rotate" Style="{DynamicResource RadioButtonStyle1}"/>
<RadioButton Width="60" Height="60" Name="zoomBoxTouchSelection" Content="Box Zoom" Style="{DynamicResource RadioButtonStyle1}" />
</ListBox>
But what I would like the buttons to look like is:
I achieved the above buttons by just overriding the default button style, but I can't seem to do it with the Toggle Button. I tried overriding Radio Button also, and I had the same problem. What am I missing? Can I somehow use the Button style instead of the toggle button style? I am just starting to learn Styles, so don't be to harsh! Appreciate all input though!
The Button in your controltemplate is creating the extra borders. If you replace Button with a Border you can style the togglebutton borders. Is there a reason you're using a Button? You can use triggers to provide the button behavior if needed. See below:
<Style x:Key="Style1" TargetType="{x:Type ToggleButton}">
<Setter Property="Background" Value="Black"/>
<Setter Property="BorderBrush" Value="Red"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Padding" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Border Name="Border" BorderThickness="1" BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" SnapsToDevicePixels="true" >
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="ToggleButton.IsMouseOver" Value="true">
<Setter TargetName="Border" Property="Background" Value="{StaticResource DarkBrush}" />
</Trigger>
<Trigger Property="IsPressed" Value="true">
<Setter TargetName="Border" Property="Background" Value="{StaticResource PressedBrush}"/>
</Trigger>
<Trigger Property="IsChecked" Value="true">
<Setter TargetName="Border" Property="Background" Value="{StaticResource CheckedBrush}" />
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="#ADADAD"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I have only tested it with Buttons, RadioButtons, and ToggleButtons, but the problem arises when trying to nest buttons withing a listbox. So I switched the code from:
<ListBox SelectionMode="Single" Name="touchPanel" Grid.Row="2" Grid.Column="3" Width="Auto" Height="Auto" VerticalAlignment="Top" Background="Black" BorderThickness="0">
<RadioButton Width="60" Height="60" Name="mouseTouchSelection" IsChecked="True" Content="Mouse" Style="{DynamicResource RadioButtonStyle1}" />
<RadioButton Width="60" Height="60" Name="panTouchSelection" BorderThickness="0" Content="Pan" Style="{DynamicResource RadioButtonStyle1}" />
<RadioButton Width="60" Height="60" Name="rotateTouchSelection" Content="Rotate" Style="{DynamicResource RadioButtonStyle1}"/>
<RadioButton Width="60" Height="60" Name="zoomBoxTouchSelection" Content="Box Zoom" Style="{DynamicResource RadioButtonStyle1}" />
</ListBox>
to:
<StackPanel Grid.Column="3" Grid.Row="2">
<RadioButton Width="60" Height="60" Name="mouseTouchSelection" IsChecked="True" Content="Mouse" Style="{DynamicResource RadioButtonStyle1}" />
<RadioButton Width="60" Height="60" Name="panTouchSelection" BorderThickness="0" Content="Pan" Style="{DynamicResource RadioButtonStyle1}" />
<RadioButton Width="60" Height="60" Name="rotateTouchSelection" Content="Rotate" Style="{DynamicResource RadioButtonStyle1}"/>
<RadioButton Width="60" Height="60" Name="zoomBoxTouchSelection" Content="Box Zoom" Style="{DynamicResource RadioButtonStyle1}" />
</StackPanel>
and I got the visual results I wanted (we will see if they work properly).
I have a combox that I have data binded to a viewmodel.
The dropdown cells are displayed properly but the comboxbox textblock doesn't show the same.
This is my combobox xaml
<ComboBox x:Name="UserComboBox" ItemsSource="{Binding userInfoViewModel.Users}"
SelectedItem="{Binding userInfoViewModel.SelectedUser, Mode=TwoWay}"
ItemTemplate="{StaticResource UserTemplate}"
ItemContainerStyle="{DynamicResource CustomUserComboBoxStyle}"
HorizontalAlignment="Left" Margin="39.025,217.76,0,186.025" Width="204.975" IsEditable="True" Background="#FFF3F3F3"
BorderBrush="{DynamicResource CustomBorder}"
Height="27.24" >
</ComboBox>
This is my UserTemplate
<DataTemplate x:Key="UserTemplate">
<StackPanel FlowDirection="LeftToRight" Orientation="Horizontal">
<TextBlock Text="{Binding Path=InternalNumber}"></TextBlock>
<TextBlock Text="{Binding Path=UserName}" ></TextBlock>
</StackPanel>
</DataTemplate>
and my CustomUserComboBoxStyle
<Style x:Key="CustomUserComboBoxStyle" TargetType="{x:Type ComboBoxItem}">
<Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
<Setter Property="VerticalContentAlignment" Value="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
<Setter Property="Padding" Value="3,0,3,0"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ComboBoxItem}">
<Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsHighlighted" Value="true">
<Setter Property="Background" Value="#646363" />
<Setter Property="Foreground" Value="#FFFFFFFF"/>
<Setter Property="BorderBrush" Value="#646363"/>
</Trigger>
<Trigger Property="IsHighlighted" Value="false">
<Setter Property="Background" Value="#FFF3F3F3" />
<Setter Property="BorderBrush" Value="#FFF3F3F3"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Why does the combobox show Digicom.Eventserver.Client.user instead of the name and number?
Your simplest solution would be to override the ToString() method in your user data class:
public override string ToString()
{
return string.Concat(InternalNumber, UserName);
}
You could set the ComboBox.DisplayMemberPath property.
That property accepts the name of only one property of the DataContext object. If you want to use two properties (InternalNumber and Username) you should use a ValueConverter or (better way IMHO) a ViewModel class