WPF ComboboxItems with button - wpf

I have created my own combobox style along with stylign combobox items. The dropdown needs to display some items with buttons and others without my items are created dynamically as follows:
ComboBoxItem typeItem = new ComboBoxItem();
typeItem.Content = "Test";
typeItem.Tag = i;
MyCombobox.Items.Add(typeItem);
My question is how do I apply this style to some items and not others, my two comboboxitems are bellow?
<Style x:Key="{x:Type ComboBoxItem}" TargetType="{x:Type ComboBoxItem}">
<Setter Property="HorizontalContentAlignment" Value="Left" />
<Setter Property="VerticalContentAlignment" Value="Top" />
<Setter Property="MinHeight" Value="{DynamicResource ResourceKey=MinimumIteractSizeDips}" />
<Setter Property="MinWidth" Value="{DynamicResource ResourceKey=MinimumIteractSizeDips}" />
<Setter Property="Foreground" Value="Black"/>
</Style>
<Style x:Key="MyComboBoxItem" TargetType="{x:Type ComboBoxItem}">
<Setter Property="HorizontalContentAlignment" Value="Left" />
<Setter Property="VerticalContentAlignment" Value="Top" />
<Setter Property="MinHeight" Value="{DynamicResource ResourceKey=MinimumIteractSizeDips}" />
<Setter Property="MinWidth" Value="{DynamicResource ResourceKey=MinimumIteractSizeDips}" />
<Setter Property="Foreground" Value="Black"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ComboBoxItem">
<Grid>
<Label Content="{TemplateBinding Content}" Foreground="Black" Background="White" Height="26" HorizontalAlignment="Left" VerticalAlignment="Center" Grid.Row="0" Grid.Column="0"/>
<Button Grid.Column="2" Grid.Row="0" Content="Settings" Height="23" HorizontalAlignment="Left" Margin="2" Name="PositionSettings" VerticalAlignment="Center" Width="57"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Check the StyleSelector class.
public class MyStyleSelector : StyleSelector
{
public override Style SelectStyle(object item, DependencyObject container)
{
var element = container as FrameworkElement;
var myVm = item as MyViewModel;
if(myVm.EditMode)
return element.FindResource("TemplateWithButtons") as DataTemplate
return element.FindResource("TemplateNormal") as DataTemplate
}
}
and in xaml, define a resource for your selector
<MyStyleSelector x:Key="myStyleSelector"/>
and apply that to your combobox.
<ComboBox StyleSelector="{StaticResource myStyleSelector}"/>
btw. x:Key with the same type as TargetType is redundant.
Final Note: You should not override the style for that. What you want is DataTemplate and the DataTemplate selector. Also you should not bind the Content(type object) to a labels text (type string), a ContentPresenter is the way to go here.

Related

WPF MVVM changing property under controltemplate programmatically

I want to change Border Background programmatically depends on WeekType property. It has All, Even and Odd property. Color of my items are in Border's Background property. So when property is All I want them to stay LightGray, but when All or Even I want to change color of this border
XAML:
<Style TargetType="{x:Type summary:SummaryHourUnitItem}">
<Setter Property="StartTime" Value="{Binding StartTime}" />
<Setter Property="EndTime" Value="{Binding EndTime}" />
<Setter Property="WeekType" Value="{Binding WeekType}" />
<Setter Property="SubGroup" Value="{Binding SubGroup}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type summary:SummaryHourUnitItem}">
<Border Width="Auto" BorderThickness="1,1,1,1" BorderBrush="Black" Background="LightGray"
Margin="0" Padding="3,1.5,0,1.5" >
<ContentPresenter>
<ContentPresenter.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="FontSize" Value="9" />
<Setter Property="Foreground" Value="Black" />
</Style>
</ContentPresenter.Resources>
</ContentPresenter>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
SummaryHourUnitItem class:
public class SummaryHourUnitItem : ButtonBase
{
public static readonly DependencyProperty StartTimeProperty =
SummaryTimeSlotPanel.StartTimeProperty.AddOwner(typeof(SummaryHourUnitItem));
public static readonly DependencyProperty EndTimeProperty =
SummaryTimeSlotPanel.EndTimeProperty.AddOwner(typeof(SummaryHourUnitItem));
public static readonly DependencyProperty WeekTypeProperty =
SummaryTimeSlotPanel.WeekTypeProperty.AddOwner(typeof(SummaryHourUnitItem));
public static readonly DependencyProperty SubGroupProperty =
SummaryTimeSlotPanel.SubGroupProperty.AddOwner(typeof(SummaryHourUnitItem));
static SummaryHourUnitItem()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(SummaryHourUnitItem),
new FrameworkPropertyMetadata(typeof(SummaryHourUnitItem)));
}
public bool StartTime
{
get => (bool) GetValue(StartTimeProperty);
set => SetValue(StartTimeProperty, value);
}
public bool EndTime
{
get => (bool) GetValue(EndTimeProperty);
set => SetValue(EndTimeProperty, value);
}
public WeekType WeekType
{
get => (WeekType) GetValue(WeekTypeProperty);
set
{
SetValue(WeekTypeProperty, value);
}
}
public SubGroup SubGroup
{
get => (SubGroup)GetValue(SubGroupProperty);
set => SetValue(SubGroupProperty, value);
}
}
How can I achieve that?
You must to use a Style Trigger.
<Border Width="Auto" BorderThickness="1,1,1,1" BorderBrush="Black" Background="LightGray"
Margin="0" Padding="3,1.5,0,1.5" >
<Border.Style>
<Style BasedOn="{StaticResource {x:Type Border}}" TargetType="{x:Type Border}">
<Setter Property="Background" Value="LightGray" />
<Style.Triggers>
<DataTrigger Binding="{Binding WeekType}" Value="XXXX">
<Setter Property="Background" Value="Red" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
<ContentPresenter>
<ContentPresenter.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="FontSize" Value="9" />
<Setter Property="Foreground" Value="Black" />
</Style>
</ContentPresenter.Resources>
</ContentPresenter>
</Border>
I hope it works for you.

Unable to bind SelectedItem of ListView when using ControlTemplate to define ListViewItem

I've defined a ListViewItem style as shown below
<Style x:Key="BaseContentStyle" TargetType="{x:Type ListViewItem}">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<ListViewItem Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
FontWeight="{TemplateBinding FontWeight}">
<ContentPresenter/>
</ListViewItem>
<ControlTemplate.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="0">
<Setter Property="Background" Value="#ebebeb"/>
</Trigger>
<DataTrigger Binding="{Binding ListViewPosition}" Value="Conference">
<Setter Property="Content" Value="{Binding Conference}"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="FontWeight" Value="SemiBold"/>
<Setter Property="Background" Value="#192942"/>
</DataTrigger>
<DataTrigger Binding="{Binding ListViewPosition}" Value="Division">
<Setter Property="Content" Value="{Binding Division}"/>
<Setter Property="BorderBrush" Value="LightGray"/>
<Setter Property="BorderThickness" Value="1.5"/>
<Setter Property="FontWeight" Value="SemiBold"/>
<Setter Property="Background" Value="Transparent"/>
</DataTrigger>
<DataTrigger Binding="{Binding ListViewPosition}" Value="Team">
<Setter Property="ContentTemplate" Value="{StaticResource MyDataTemplate}"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I've defined my ListView as follows
<ListView ItemsSource="{Binding AmericanAthleticTeams}"
SelectedItem="{Binding Path=SelectedTeam, Mode=TwoWay}"
ItemContainerStyle="{StaticResource BaseContentStyle}">
This is the DataTemplate used for the ContentTemplate in the Style template
<DataTemplate x:Key="MyDataTemplate" >
<Grid >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="3*"/>
</Grid.ColumnDefinitions>
<Image Source="{Binding Logo, Converter={StaticResource imageConverter}}"
RenderOptions.BitmapScalingMode="Fant"
Grid.Column="0"
Height="15"
Width="15"
HorizontalAlignment="Left"
Margin="5 0 0 0"/>
<TextBlock Text="{Binding Name}"
Grid.Column="1"
HorizontalAlignment="Left"
VerticalAlignment="Center"/>
</Grid>
</DataTemplate>
And here is the ViewModel serving as the View's DataContext
class NCAAFBTeamsViewModel : ViewModelBase
{
public List<NCAAFBTeamViewModel> AmericanAthleticTeams { get; set; }
private NCAAFBTeamViewModel team;
public NCAAFBTeamsViewModel(List<NCAAFBTeamViewModel> americanAthleticTeams)
{
AmericanAthleticTeams = americanAthleticTeams;
}
public NCAAFBTeamViewModel SelectedTeam
{
get { return team; }
set
{
team = value;
OnPropertyChanged();
}
}
}
The problem I'm running into is the binding for the SelectedItem property of the ListView doesn't work as intended. In particular, when I click on one of the displayed ListViewItems, the trigger isn't invoked for the bound SelectedTeam property in the ViewModel. I believe the issue resides with the ControlTemplate of my Style and that perhaps I'm not bubbling up high enough. I've scoured Google and unfortunately wasn't able to discover anything with regards to issues encountered with using a ControlTemplate to define ListViewItems and the impact it has on the SelectedItem property. Any help would be greatly appreciated!

Silverlight datagrid columnheader change font color

Is it possible to change the font color for the column headers in a datagrid?
I've already applied some styling which changes the background, but i can't figure out how to change the font color, not for the element, but for the header.
the XAML I'm using is from this thread: Change background color of Datagrid Header in Silverlight
Hi add a style to your resource and set the style,
<Style x:Key="GridHeaderStyle" ControlTemplate TargetType="primitives:DataGridColumnHeader">
<Setter Property="FontSize"
Value="14" />
<Setter Property="FontWeight"
Value="Bold" />
<Setter Property="Foreground"
Value="{StaticResource xrxGray_I}" />
<Setter Property="Background"
Value="{StaticResource xrxGray_B}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid Height="50" Width="100">
<TextBlock Text="{TemplateBinding Header}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>

Silverlight 4 DataGrid column header style

I am trying to affect the background pattern on a DataGrid in Silverlight 4. I have the following style:
<Style x:Key="DashboardGridHeaderStyle"
TargetType="primitives:DataGridColumnHeader">
<Setter Property="FontSize"
Value="14" />
<Setter Property="FontWeight"
Value="Bold" />
<Setter Property="Foreground"
Value="{StaticResource xrxGray_I}" />
<Setter Property="Background"
Value="{StaticResource xrxGray_B}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid Height="50" Width="100">
<TextBlock Text="{TemplateBinding Header}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
This causes an exception when it is applied. This is caused by the Template setter. Does anyone know how to change the background of the column header (I want a solid color instead of the default gradient)?
Thanks for any help.
Your ControlTemplate element is missing the TargetType property it should like this:-
<ControlTemplate TargetType="primitives:DataGridColumnHeader">

Creating a common window look in WPF

How would I create a common window look in WPF? I'm not talking about just styling the window, I'm mean having a window that has a border, grid, and some other things in it.
Thanks.
You can create a ControlTemplate for the window. Here is a pretty basic example that has some controls and triggers. You can easily add more elements to make it fit your needs.
<ControlTemplate x:Key="MyWindowTemplate" TargetType="{x:Type Window}">
<Border x:Name="WindowBorder" Style="{DynamicResource WindowBorderStyle}">
<Grid>
<Border Margin="4,4,4,4" Padding="0,0,0,0" x:Name="MarginBorder">
<AdornerDecorator>
<ContentPresenter/>
</AdornerDecorator>
</Border>
<ResizeGrip Visibility="Collapsed" IsTabStop="false" HorizontalAlignment="Right" x:Name="WindowResizeGrip"
VerticalAlignment="Bottom" />
</Grid>
</Border>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="ResizeMode" Value="CanResizeWithGrip"/>
<Condition Property="WindowState" Value="Normal"/>
</MultiTrigger.Conditions>
<Setter Property="Visibility" TargetName="WindowResizeGrip" Value="Visible"/>
<Setter Property="Margin" TargetName="MarginBorder" Value="4,4,4,20" />
</MultiTrigger>
<Trigger Property="WindowState" Value="Maximized">
<Setter Property="CornerRadius" TargetName="WindowBorder" Value="0,0,0,0"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
You can use this ControlTemplate by setting the template property of the Window:
Template="{StaticResource MyWindowTemplate}"
You will want to use this in conjunction with a style like this:
<Style x:Key="MyWindowStyle" TargetType="{x:Type Window}">
<Setter Property="AllowsTransparency" Value="False" />
<Setter Property="WindowStyle" Value="SingleBorderWindow" />
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}"/>
<Setter Property="Background" Value="Transparent" />
<Setter Property="ShowInTaskbar" Value="False" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Window}">
<Border>
<AdornerDecorator>
<ContentPresenter/>
</AdornerDecorator>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And set the style on your Window like this:
Style="{StaticResource MyWindowStyle}"
What I ended up doing was creating a base class that created the UI code that I wanted in every window. This allows me to set events for controls and have the event subscription in the base class. If there is a better way of doing this, like using xaml, I'd like to know.
public WindowBase()
{
Initialized += WindowBase_Initialized;
}
private void WindowBase_Initialized( object sender, EventArgs e )
{
Border border = new Border();
border.SetResourceReference( Control.StyleProperty, "WindowBorder" );
border.Child = new ContentPresenter { Content = this.Content};
this.Content = border;
}

Resources