Creating Combo Box UserControl with Multi Column - wpf

I have multi-column combo box but i want to use these combo box in many places.So I think i need to create combo box user control.But problem is itemsource of each combo box is not same.
Currently my multi column combo box,
<ComboBox Grid.Row="0"
Grid.Column="1"
Margin="2"
Width="150"
x:Name="cboemployee"
IsEditable="True"
DisplayMemberPath="EmployeeID"
SelectedValuePath="EmployeeID"
ItemsSource="{Binding EmployeeList}">
<ComboBox.ItemContainerStyle>
<Style TargetType="{x:Type ComboBoxItem}" BasedOn="{StaticResource MetroComboBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid Width="400" x:Name="gd">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="300"/>
</Grid.ColumnDefinitions>
<TextBlock Margin="2" Grid.Column="0" Text="{Binding EmployeeID}"/>
<TextBlock Margin="2" Grid.Column="1" Text="{Binding EmployeeName}"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="ComboBoxItem.IsSelected" Value="True">
<Setter TargetName="gd" Property="Background" Value="{StaticResource AccentBaseColorBrush}"></Setter>
<Setter TargetName="gd" Property="TextElement.Foreground" Value="White"></Setter>
</Trigger>
<Trigger Property="ComboBoxItem.IsMouseOver" Value="True">
<Setter TargetName="gd" Property="Background" Value="{StaticResource AccentColorBrush}"></Setter>
<Setter TargetName="gd" Property="TextElement.Foreground" Value="White"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ComboBox.ItemContainerStyle>
</ComboBox>
I am not sure i need custom combo box or combo box user control and Please let me known which is best for my requirement with binding different item source?

Related

Solved - Setting DataGridColumnHeader template with predefined columns adds too much columns

I have the following DataGrid:
<DataGrid Grid.Row="2" ItemsSource="{Binding Rejects}" AutoGenerateColumns="False" Style="{StaticResource DataGridStyle}" ColumnHeaderStyle="{StaticResource DataGridHeaderStyle}">
<DataGrid.Columns>
<DataGridTextColumn Header="First column" Binding="{Binding Id}"/>
</DataGrid.Columns>
</DataGrid>
The ItemsSource is bound to a property of my ViewModel called Rejects, which is an ObservableCollection of Dummy objects.
Here is the style called DataGridHeaderStyle:
<Style x:Key="DataGridHeaderStyle" TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="Height" Value="30"/>
<Setter Property="Background" Value="{StaticResource EasternBlueBrush}"/>
<Setter Property="Foreground" Value="{StaticResource WhiteBrush}"/>
<Setter Property="BorderBrush" Value="{StaticResource DarkGreyBrush}"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="Padding" Value="10 0"/>
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Text="{Binding}"/>
</DataTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="DataGridColumnHeader">
<ControlTemplate.Resources>
<converters:DebugConverter x:Key="DebugConverter"/>
</ControlTemplate.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Border Background="{TemplateBinding Background}" Padding="5">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center">
<TextBlock x:Name="SortArrow" Margin="0 0 5 0"/>
<ContentPresenter Content="{Binding}"/>
</StackPanel>
</Border>
<Thumb x:Name="PART_RightHeaderGripper" Grid.Column="1"
HorizontalAlignment="Right"
Width="2"
BorderThickness="1"
BorderBrush="{StaticResource EasternBlueBrush}"
Cursor="SizeWE"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="ToolTip" Value="Click to sort."/>
<Setter Property="Background" Value="{StaticResource CuriousBlueBrush}"/>
</Trigger>
<Trigger Property="SortDirection" Value="Ascending">
<Setter TargetName="SortArrow" Property="Visibility" Value="Visible"/>
<Setter TargetName="SortArrow" Property="Text" Value="↓"/>
</Trigger>
<Trigger Property="SortDirection" Value="Descending">
<Setter TargetName="SortArrow" Property="Visibility" Value="Visible"/>
<Setter TargetName="SortArrow" Property="Text" Value="↑"/>
</Trigger>
<Trigger Property="SortDirection" Value="{x:Null}">
<Setter TargetName="SortArrow" Property="Visibility" Value="Collapsed"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I was expecting to have only one column called "First column", but here is the result:
Result
As you can see, there is an other column called by the name of my ViewModel that appears. This doesn't happen when I remove the Template property.
Also, while this new column looks like the other one, it doesn't react when hovered.
EDIT
As I said under #ketan's answer, I was able to remove the weird column header by setting the DataContext of my DataGrid to {x:Null} and by setting the ItemsSource directly from the code-behind, which shows that the problem is linked to the DataGrid's DataContext, but I still need to keep it, any idea?
Also, here's the list I use as ItemsSource:
public ObservableCollection<Dummy> Rejects { get; set; } = new ObservableCollection<Dummy>()
{
new Dummy()
{
Id = 1,
Prop1 = "A"
},
new Dummy()
{
Id = 2,
Prop1 = "B"
}
};
SOLUTION
I finally found out what was going wrong. It's all linked to the Content property of my ContentPresenter inside the template: I set the Content property instead of the ContentSource. Thus, the solution is:
<ContentPresenter ContentSource="Header"/>
<DataGrid Grid.Row="2" x:Name="gridDemo" ItemsSource="{Binding lst}" AutoGenerateColumns="False" Loaded="gridDemo_Loaded_1" >
<DataGrid.Columns>
<DataGridTextColumn Width="*" Header="First column" Binding="{Binding id}"/>
</DataGrid.Columns>
</DataGrid>
pass the colun width to *

How to show current position of a slider over the thumb always

How to show a slider control with a tooltip/label under the thumb showing the value (timespan) always while it moves with/without user dragging.
I tried AutoToolTipPlacement="BottomRight" AutoToolTipPrecision="3" on my slider.
But Tooltip gets displayed only when i drag the thumb. I want that shown even when i invoke playing slider with a button control.(like video player)
The point is to reduce the size of my usercontrol and avoid extra labels for timers or position.
If i am in the wrong direction, please suggest me better ideas. Thanks!
You can re-style the Thumb to show this effect. Below is a sample that makes a circular Thumb with the .Value property of the parent Slider showing up inside the circle.
<Style TargetType="{x:Type Thumb}">
<Setter Property="Focusable" Value="false"/>
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="Height" Value="20"/>
<Setter Property="Width" Value="20"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Thumb}">
<Canvas SnapsToDevicePixels="true">
<Grid Height="20" Width="20">
<Ellipse x:Name="Background"
Fill="#FFA3A3A3"
Height="20" Width="20"
Stroke="#FFDADADA"/>
<TextBlock HorizontalAlignment="Center"
VerticalAlignment="Center"
Foreground="Black"
FontSize="9"
Text="{Binding Value, RelativeSource={RelativeSource AncestorType={x:Type Slider}}, Converter={StaticResource ConvertToIntegerConverter}}"/>
</Grid>
</Canvas>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Fill" TargetName="Background"
Value="#FFDADADA"/>
</Trigger>
<Trigger Property="IsDragging" Value="true">
<Setter Property="Fill" TargetName="Background"
Value="#FFF2F2F2"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Fill" TargetName="Background"
Value="#FFF2F2F2"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I've used an IValueConverter to make sure the the value displayed is always an integer, since the normal .Value property is a decimal. You would want to use your own converter to properly format the information that you want displayed.
You can make the text or numbers appear wherever you want by re-styling the Thumb.
EDIT:
If you want to show the text above or below the actual thumb, it's a pretty minor change to the styling:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="20"/>
<RowDefinition Height="20"/>
</Grid.RowDefinitions>
<Ellipse x:Name="Background"
Fill="#FFA3A3A3"
Height="20" Width="20"
Stroke="#FFDADADA"/>
<TextBlock Grid.Row="1" HorizontalAlignment="Center"
VerticalAlignment="Center"
Foreground="White"
FontSize="9"
Text="{Binding Value, RelativeSource={RelativeSource AncestorType={x:Type Slider}}, Converter={StaticResource ConvertToIntegerConverter}}"/>
</Grid>

Xaml Border issue

I am using HeaderedContentControl for displaying my label & text box as below..
<Style x:Key="ContentBorderStyle" TargetType="Border">
<Setter Property="BorderBrush" Value="Blue"/>
</Style>
<Style TargetType="HeaderedContentControl" x:Key="BaseLabeledItemStyle">
<Style.Setters>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="HeaderedContentControl">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Border Grid.Column="0">
<ContentPresenter Name="header"
Content="{TemplateBinding Header}"/>
</Border>
<Border Grid.Column="1"
Style="{StaticResource ContentBorderStyle}">
<AdornerDecorator>
<ContentPresenter Name="content"
Content="{Binding RelativeSource={RelativeSource TemplatedParent},Path=Content}"/>
</AdornerDecorator>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style.Setters>
</Style>
<HeaderedContentControl
Style="{StaticResource ResourceKey=BaseLabeledItemStyle}"
Header="Emp Name">
<!--<ContentControl>-->
<TextBox x:Name="txtName"
Text="{Binding Path=EmpName, Mode=TwoWay, ValidatesOnDataErrors=True}"/>
</HeaderedContentControl>
As I am using Border brush as "Blue" for content control My content Control is always displaying with Blue border. When there is an validation error, my text box which I am using inside Headered content control's border is changing to red as I am using ValidationOnDataerror. now my requirement is to change even the content border too in Red Color when Validation occurs (i.e. when inner text box is in red color)...
I am attaching an Image how my control is populating.. in that (1) is border of my content control & (2) is my text box control.
How can I change the color of content control based on Text box color...
thanks in advance...
You could use a DataTrigger for additional highlighting
<Style x:Key="ContentBorderStyle" TargetType="Border">
<Setter Property="BorderBrush" Value="Blue"/>
<Style.Triggers>
<DataTrigger Binding="{Binding (Validation.HasError), ElementName=txtName}" Value="True">
<Setter Property="BorderBrush" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
FYI:
If you want to show the Validation.ErrorTemplate on any other control than TextBox use Validation.ValidationAdornerSiteFor Attached Property. e.g.
<HeaderedContentControl Validation.ValidationAdornerSiteFor="{Binding ElementName=txtName}"
or
<Style x:Key="ContentBorderStyle" TargetType="Border">
<Setter Property="BorderBrush" Value="Blue"/>
<Setter Property="Validation.ValidationAdornerSiteFor" Value="{Binding ElementName=txtName}"/>
</Style>

wpf listbox checkbox change color when checked or selected

I have tried the different examples on this site to get the list box / check box combo to change from the default gray when selected to another color to no avail.
What I am trying to do in the end is if the item is checked, the background will be white, and when unchecked it will gray out.
Here is what I have and any help would be appreciated.
Update the resource to the comment below.
The control has been updated to the reply and still not working, any ideas?
<ListBox ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ItemsSource="{Binding}"
Name="lstSwimLane" SelectionMode="Multiple"
Width="auto"
Height="auto"
Background="Transparent"
BorderThickness="0"
SelectionChanged="LstSwimLaneSelectionChanged">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="IsSelected" Value="{Binding Path=IsChecked, Mode=TwoWay}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border x:Name="Border" SnapsToDevicePixels="true">
<ContentPresenter />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Border" Property="Background" Value="{StaticResource SelectedBrush}"/>
</Trigger>
<Trigger Property="IsSelected" Value="False">
<Setter TargetName="Border" Property="Background" Value="{StaticResource UnselectedBrush}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="3,3,3,3">
<CheckBox IsChecked="{Binding RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}, Path=IsSelected}"
Checked="ChkFilterChecked"
Unchecked="ChkFilterUnchecked"
VerticalAlignment="Center"
Margin="0,0,4,0" />
<TextBlock Text="{Binding Value}" VerticalAlignment="Center" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Note: The checked checkboxes and list item combination is still gray and the unchecked is white.
Attached is a screen shot which seems to match the reply have below. I am stumped.
Here is the direct link in order to see the image bigger.
http://s1120.photobucket.com/albums/l489/nitefrog/?action=view&current=jw_0012011-03-311325.jpg
Here is the screen shot of the checkboxes.
http://i1120.photobucket.com/albums/l489/nitefrog/jw_0022011-03-311345.jpg
Even though the brushes are set, for some reason they are not being triggered.
Any ideas?
Thanks.
My example doesn't use the myListboxStyle style, you can remove it. But change the ItemContainerStyle property:
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="IsSelected" Value="{Binding Path=IsChecked, Mode=TwoWay}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border x:Name="Border" SnapsToDevicePixels="true">
<ContentPresenter />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Border" Property="Background" Value="{StaticResource SelectedBrush}"/>
</Trigger>
<Trigger Property="IsSelected" Value="False">
<Setter TargetName="Border" Property="Background" Value="{StaticResource UnselectedBrush}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
It is very simple template and it has only two triggers: IsSelected=True and IsSelected=False.
And to complete this example add these brushes to the Resources collection:
<SolidColorBrush x:Key="SelectedBrush" Color="White"/>
<SolidColorBrush x:Key="UnselectedBrush" Color="Gray"/>
It would be better to edit the standard style for the ListViewItem, but I can't find it in the internet and I don't have Expression Blend now.
Screen of the result:

AdornerDecorator and tab stop issues

I am using IDataErrorInfo to validate and indicate errors in my text boxes. I am finding I have to tab once for the text box and once for the adornerdecorator.
I have an error template:
<ControlTemplate x:Key="ErrorTemplate">
<StackPanel KeyboardNavigation.IsTabStop="False" >
<Border KeyboardNavigation.IsTabStop="False" BorderBrush="Red" BorderThickness="1" Padding="2" CornerRadius="2">
<AdornedElementPlaceholder KeyboardNavigation.IsTabStop="False" />
</Border>
</StackPanel>
</ControlTemplate>
a textbox template:
<Style x:Key="TextBoxInError" TargetType="{x:Type TextBox}">
<Setter Property="KeyboardNavigation.TabNavigation" Value="None"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Margin" Value="0,5,0,5"/>
<Setter Property="AllowDrop" Value="true"/>
<Setter Property="HorizontalContentAlignment" Value="left"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Grid KeyboardNavigation.IsTabStop="False" >
<Border KeyboardNavigation.IsTabStop="False" x:Name="Border" Background="{DynamicResource WindowBackgroundBrush}" BorderBrush="{DynamicResource SolidBorderBrush}" BorderThickness="1" Padding="2" CornerRadius="2">
<ScrollViewer IsTabStop="False" Margin="0" x:Name="PART_ContentHost" Style="{DynamicResource SimpleScrollViewer}" Background="{TemplateBinding Background}"/>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors), Converter={StaticResource errorConverter}}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="Gray"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
and declare a text box like this:
<AdornerDecorator KeyboardNavigation.IsTabStop="False" >
<TextBox Margin="5,5,5,3" x:Name="txtName" IsEnabled="{Binding EditMode}" Validation.ErrorTemplate="{StaticResource ErrorTemplate}"
Text="{Binding ApplicationName, Mode=TwoWay, ValidatesOnExceptions=True, NotifyOnValidationError=True, ValidatesOnDataErrors=True}"
Height="25" MaxLength="50" MaxLines="1" Style="{StaticResource TextBoxInError}"/>
</AdornerDecorator>
If the adorner is round one text box as above then I tab once to leave the text box and once to leave the 'adornment' (it seems) If I have the adorner around a stackpanel of text boxes then I tab once each for the text boxes then have to go back through all the 'adornments' in turn. When tabbing through the adornments the focus goes on the red border defined in the control template..
any ideas?
thanks
Add this to the window's resources section:
<Style TargetType="{x:Type Control}">
<Setter Property="Focusable" Value="False"/>
</Style>
For more information look at my blog: http://www.nbdtech.com/blog/archive/2008/05/25/WPF-Problems-with-Keyboard-Focus-When-Using-Validation.aspx

Resources