How to apply style to a custom control - c#

I have a custom control inheriting from ListBox.
I have a style for it targeting my custom control.
For some reason this style is not working on my custom control.
Could you please tell me what I am missing here?
Code for style:
<Style x:Key="ListBoxStyle" TargetType="local:CustomListBox">
<Setter Property="Background" Value="Red"/>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center"/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
Code for custom control:
public class CustomListBox : ListBox
{
public CustomListBox()
{
this.DefaultStyleKey = typeof(CustomListBox).Name;
}
}
Usage of custom control:
<local:CustomListBox>
<ListBoxItem Content="AAA"></ListBoxItem>
<ListBoxItem Content="BBB"></ListBoxItem>
<ListBoxItem Content="CCC"></ListBoxItem>
</local:CustomListBox>
Any help?
Thank you!

In Windows Phone 8.1 when you create a Templated Control (Custom control) a file is automatically created called Generic.xaml under Themes folder.
Your style should be added in Generic.xaml like this.
<Style TargetType="local:CustomListBox">
<Setter Property="Background" Value="Red"/>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center"/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
Change the following line to
this.DefaultStyleKey = typeof(CustomListBox);

Related

How to bind and display a set of colors in WPF listview?

Im struggling with a problem that might seem easy first: I want to display some grid with different colors. I have a listview that is binded to a list. The list containst Colors (i have tried SolidColorBrush as well). The listview can display the elements, so in the current case you can see 1 grid per item. I want to bind the background of the grid (so the datatemplate) to the color property itself. For example: lets say i have a white and black color in my list. Then i want to display a black and a white grid using listview.
However, i cannot bind the background to anything, the binding always fails and I couldnt find a solution.
Here is the xaml code:
<ListView ItemsSource="{Binding lightColors}" Height="30" HorizontalAlignment="Left">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Margin" Value="5"></Setter>
<Setter Property="Background" Value="{Binding **WHAT TO WRITE HERE?**}"></Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListViewItem">
<Grid Height="30" Width="30"></Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel>
</WrapPanel>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate>
</DataTemplate>
</ListView.ItemTemplate>
And some code snippets:
public List<Color> lightColors { get; set; }
public void fillLightColors()
{
Color myColor = Color.FromRgb(100, 150, 75);
LightColor.Add(myColor);
}
Currently i cant see anything whenever i try to bind to the background.
Maybe im missing something obvious, maybe i have to use something totally else. Any help would be appriciated!
You would use a SolidColorBrush as value of the Setter:
<Setter Property="Background">
<Setter.Value>
<SolidColorBrush Color="{Binding}"/>
</Setter.Value>
</Setter>
Besides that, the ControlTemplate must also use the Background property:
<ControlTemplate TargetType="ListViewItem">
<Grid Height="30" Width="30"
Background="{TemplateBinding Background}"/>
</ControlTemplate>
Also note that when you set the ListViewItem's Template like this, the ItemTemplate is not used at all. The ControlTemplate should have a ContentPresenter.
<ControlTemplate TargetType="ListViewItem">
<Grid Height="30" Width="30"
Background="{TemplateBinding Background}">
<ContentPresenter/>
</Grid>
</ControlTemplate>
How about this:
Style:
<Style x:Key="ColorComboStyle" TargetType="{x:Type ComboBox}">
<Setter Property="ItemsSource" Value="{Binding Path=(global:GlobalVars.AllBrushes)}"/>
<Setter Property="SelectedValuePath" Value="Name"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<Grid HorizontalAlignment="Stretch" Height="24">
<DockPanel LastChildFill="True" HorizontalAlignment="Stretch">
<Rectangle DockPanel.Dock="Right" Fill="{Binding}" Stroke="Black" StrokeThickness="1" Height="20" Width="20"/>
<Label Padding="2" Content="{Binding}" VerticalAlignment="Center" HorizontalAlignment="Left"/>
</DockPanel>
</Grid>
</DataTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemContainerStyle">
<Setter.Value>
<Style TargetType="{x:Type ComboBoxItem}">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
</Setter.Value>
</Setter>
</Style>
The GlobarVars property looks like this:
public static List<string> AllBrushes { get; } = typeof(Brushes).GetProperties().Select(x => x.Name).ToList();
Then use a ComboBox like this:
<ComboBox Style="{StaticResource ColorComboStyle}" SelectedValue="{Binding ...}"/>
Worked very well in my case... You will just need to adapt the code to work in your ListView.

Add wrapping to certain controls

I need to add wrapping to my Radio Button controls all but for on one window. I am stuck trying to figure out how I can conditionally remove or change the value of my wrap panel from my control when the radio buttons are added to a different page that does not need wrapping.
This is the coding to add the wrapping.
XAML
<Style TargetType="auc:APRadioButtonListBox">
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled" />
<Setter Property="IsTabStop" Value="True" />
<Setter Property="FontSize" Value="{StaticResource FontSize}" />
<Setter Property="Margin" Value="-2,0,0,0" />
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<toolkit:WrapPanel Background="Transparent" ItemWidth="Auto" x:Name="RadioListWrapPanel" Orientation="Horizontal" />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemTemplate">
C#
public virtual ItemsPanelTemplate ItemsPanel { get; set; }
Can anybody advice me on how to add Radio buttons to another page without the wrapping.
Since you have the style applied at the application level, it will be applied implicitly to all controls that match its target type. You have two options to get a page without wrapping...
Override the style on the required pages with a style that omits the wrapping
Give the default style you have a key and explicitly apply it where it's needed and others won't have the wrapping.
The latter makes sense if more pages have no need for the wrapping than those that do. Consider the following
<Style x:Key="WrappedRadioButtons" TargetType="auc:APRadioButtonListBox">
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled" />
<Setter Property="IsTabStop" Value="True" />
<Setter Property="FontSize" Value="{StaticResource FontSize}" />
<Setter Property="Margin" Value="-2,0,0,0" />
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<toolkit:WrapPanel Background="Transparent" ItemWidth="Auto" x:Name="RadioListWrapPanel" Orientation="Horizontal" />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemTemplate">
</Style>
Now in the pages you need to apply this style, you can do the following:
<uac:APRadioButtonListBox Style="{StaticResource WrappedRadioButtons}" />
Any other that doesn't explicitly reference this style will get the default settings. Alternatively, you can define the other style without wrapping and give it a key that you can apply to the pages that don't require the wrapping.
create a new style derived from base and override style setter on a page where WrapPanel is not required
<Style TargetType="auc:APRadioButtonListBox"
BasedOn="{StaticResource {x:Type auc:APRadioButtonListBox}}">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
or simply do it for auc:APRadioButtonListBox element:
<auc:APRadioButtonListBox>
<auc:APRadioButtonListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</auc:APRadioButtonListBox.ItemsPanel>
</auc:APRadioButtonListBox>
alternatively define a named style in resource dictionary which doesn't set ItemsPanel. default style will extend it. and on one page which doesn't need wrapping use named style:
<Style TargetType="auc:APRadioButtonListBox" x:Key="APRadioButtonListBoxStyle">
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled" />
<Setter Property="IsTabStop" Value="True" />
<Setter Property="FontSize" Value="{StaticResource FontSize}" />
<Setter Property="Margin" Value="-2,0,0,0" />
</Style>
<Style TargetType="auc:APRadioButtonListBox" BasedOn="{StaticResource APRadioButtonListBoxStyle}">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<toolkit:WrapPanel Background="Transparent" ItemWidth="Auto" x:Name="RadioListWrapPanel" Orientation="Horizontal" />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
<auc:APRadioButtonListBox Style="{StaticResource APRadioButtonListBoxStyle}"/>

Checked event firing when grouping added to DataGrid - WPF C#

I'm having a problem where when adding grouping to my datagrid; the event I have defined as "Checkbox.Checked" gets called when it shouldn't be.
When this line of code is not commented out "collection.GroupDescriptions.Add(new PropertyGroupDescription("_group"));" the bug occurs.
Upon starting my application with this line in, the first check of any checkbox works as it should, then on the second click, if I click literally anywhere on the datagrid, the checked event will be fired.
Do any of you have any idea?
Thanks.
I have events define on my DataGrid like this;
<DataGridCheckBoxColumn.CellStyle>
<Style>
<EventSetter Event="CheckBox.Checked" Handler="Method_checked"/>
<EventSetter Event="CheckBox.Unchecked" Handler="Method_Unchecked"/>
</Style>
</DataGridCheckBoxColumn.CellStyle>
I have since added grouping to my data using the following code in C#;
ListCollectionView collection = new ListCollectionView(listOfData);
collection.GroupDescriptions.Add(new PropertyGroupDescription("_group"));
dgData.ItemsSource = collection;
I have added groups to my datagrid adding the following code in xaml;
<DataGrid.GroupStyle>
<GroupStyle ContainerStyle="{StaticResource GroupHeaderStyle}">
<GroupStyle.Panel>
<ItemsPanelTemplate>
<DataGridRowsPresenter/>
</ItemsPanelTemplate>
</GroupStyle.Panel>
</GroupStyle>
You may noticed "GroupHeaderStyle" which is defined above;
<Window.Resources>
<Style x:Key="GroupHeaderStyle" TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Expander x:Name="exp" IsExpanded="True"
Background="White"
Foreground="Black">
<Expander.Header>
<TextBlock Text="{Binding Name}" />
</Expander.Header>
<ItemsPresenter/>
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>

ItemsPanelTemplate Selector in wpf?

I need to set the ItemsPanelTemplate property of a listbox based on a dependency property on the control. How do I use the DataTemplateSelector to do that?
I have something like:
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<!-- Here I need to replace with either a StackPanel or a wrap panel-->
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
Thanks
There isn't an ItemsPanelSelector (probably because it isn't a DataTemplate) but you can bind it or use a Trigger
Binding example
<ListBox ItemsPanel="{Binding RelativeSource={RelativeSource Self},
Path=Background,
Converter={StaticResource MyItemsPanelConverter}}">
Trigger in Style example
<ListBox ItemsSource="{Binding Source={x:Static Fonts.SystemFontFamilies}}">
<ListBox.Style>
<Style TargetType="ListBox">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<StackPanel/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<!-- Your Trigger.. -->
<Trigger Property="Background" Value="Green">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<WrapPanel/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</ListBox.Style>
</ListBox>
I'm thinking the best route here would be to use a Style for your ListBox and set Triggers that change the ItemsPanel based on the DependencyProperty you reference.

Silverlight 4 custom control child items style

I have custom control where i want to show some items.
In generic.xaml defined style for custom control:
<Style TargetType="local:Custom">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:Customl">
<!-- Root Grid-->
<Grid x:Name="CustomLayout"
Background="Black">
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And i set to C#
[TemplatePart(Name = "CustomLayout", Type = typeof(Grid))]
[StyleTypedProperty(Property = "ChildItemStyle", StyleTargetType = typeof(Control))]
public class GaugeControl : Control
Everything working fine excepts style for child items
defined in
generic.xaml:
<Style TargetType="{x:Type Control}">
<Setter Property="Background" Value="Red"></Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Control}">
<!-- Root Grid-->
<Grid x:Name="LayoutRoot"
Background="Red">
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Custom control with attribute
[StyleTypedProperty(Property = "ChildItemStyle", StyleTargetType = typeof(Control))]
And i have ChildItemStyle DependencyProperty in my custom control but its always null.
How can i get this Style property and whats wrong i am doing?
I found solution and bug in my code.
I just add setter to my <Style TargetType="local:Custom"> definition and with help of setter set ChildItemStyle which i want.

Categories