WPF: Prevent ComboBox from displaying selected item - c#

I have a ComboBoxthat I have templated to look like this:
Here is the XAML for this ComboBox:
<ComboBox Name="StateInclusionRules_ComboBox"
ItemsSource="{Binding StateInclusionRules}"
Height="25"
Width="155"
Margin="0"
Grid.Column="7">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal"
Margin="0">
<Label Content="{Binding State}"
Margin="0,0,0,0"
Width="30" />
<CheckBox IsChecked="{Binding StateTax}"
Margin="20,0,0,0"/>
<CheckBox IsChecked="{Binding StateChildSupport}"
Margin="30,0,0,0"/>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
Is there a way to prevent the selected item from being displayed in the ComboBox ContentPresenter (the red bordered area, i.e, the area you see when the ComboBox is closed)?

First you need 2 DataTemplates, 1 for the selected item and 1 for the drop down item.
The selected we are going to leave empty because this is your requirment.
The drop down item DataTemplate will have the exact DataTemplate you wanted.
When item is selected a DataTrigger will change it's template to the SelectedTemplate, like so:
<Window.Resources>
<DataTemplate x:Key="DropDownItemTemplate" DataType="wpfApplication1:ItemSourceModel">
<StackPanel Orientation="Horizontal"
Margin="0">
<Label Content="{Binding Value}"
Margin="0,0,0,0"
Width="30" />
<CheckBox IsChecked="{Binding Value}"
Margin="20,0,0,0"/>
<CheckBox IsChecked="{Binding Value}"
Margin="30,0,0,0"/>
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="SelectionBoxTemplate">
</DataTemplate>
<DataTemplate x:Key="ComboBoxTemplate">
<ContentPresenter x:Name="Presenter"
Content="{Binding}"
ContentTemplate="{StaticResource DropDownItemTemplate}" />
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor,ComboBoxItem,1}}" Value="{x:Null}">
<Setter TargetName="Presenter" Property="ContentTemplate" Value="{StaticResource SelectionBoxTemplate}" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</Window.Resources>
And set your ComboBox with the ComboBoxTemplate:
<ComboBox Name="StateInclusionRules_ComboBox"
ItemsSource="{Binding YourItemSource}" ItemTemplate="{StaticResource ComboBoxTemplate}"
Height="25"
Width="155"
Margin="0"
/>

Related

Add Styling to First Item in ListView XAML

I have a ListView as such:
<ListView ItemsSource="{Binding SourceItems}" Grid.Row="1">
<ListView.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Black" BorderThickness="1, 1, 0, 0">
<Grid>
<Label Content="{Binding PropertyName}" FontSize="15"/>
<CheckBox IsChecked="{Binding IsChecked, Mode=TwoWay}"
HorizontalAlignment="Right"
VerticalAlignment="Center"/>
</Grid>
</Border>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
This listview sets up each row to have a Label and Checkbox as included above. What I want to do is add styling so that the first item in the listview has a different color background so that it distinguishes the start of the listview items.
I have tried adding this ItemContainerStyle, which works in changing the color of the first item, but it affects the styling of the borderbrush and checkbox alignment.
<ListView ItemsSource="{Binding SourceItems}" Grid.Row="0">
<ListView.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Black" BorderThickness="1, 1, 0, 0">
<Grid>
<Label Content="{Binding PropertyName}" FontSize="15"/>
<CheckBox IsChecked="{Binding IsChecked, Mode=TwoWay}"
HorizontalAlignment="Right"
VerticalAlignment="Center" />
</Grid>
</Border>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource PreviousData}}" Value="{x:Null}">
<Setter Property="Background" Value="Blue" />
<Setter Property="Foreground" Value="White"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>
</ListView>
Is there a way to change this xaml so that the Checkbox styling is as used in the DataTemplate?
In your source Data "SourceItems" can you add a property
public Color BackgroundColorValue { get; set; }
And set it while the data is fetched from the source.
Then bind the background property directly
<ListView ItemsSource="{Binding SourceItems}" Grid.Row="1">
<ListView.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Black" BorderThickness="1, 1, 0, 0">
<Grid Background={Binding BackgroundColorValue}>
<Label Content="{Binding PropertyName}" FontSize="15"/>
<CheckBox IsChecked="{Binding IsChecked, Mode=TwoWay}"
HorizontalAlignment="Right"
VerticalAlignment="Center"/>
</Grid>
</Border>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>

Display a StackPanel only if one of two options are selected in a radio button

I have a WPF application and one page shows two stack panels with radio buttons in them. I want to have it so that the visibility of the second stack panel is dependent on whether certain radio buttons are selected or not.
<Grid Background="#F8FBFD">
<StackPanel x:Name="StackType" HorizontalAlignment="Center" Orientation="Horizontal" Margin="0,93,0,428">
<materialDesign:Card Padding="32" Margin="16">
<StackPanel>
<TextBlock HorizontalAlignment="Left" Style="{DynamicResource MaterialDesignTitleTextBlock}" >Installation Type</TextBlock>
<RadioButton Checked="NewMode_Checked" Content="New " x:Name="rbtnNew" GroupName="InstallType" IsChecked="{Binding newMode, Mode=TwoWay, Source={StaticResource modes}}"/>
<RadioButton Checked="UpgradeMode_Checked" Content="Update" x:Name="rbtnUpgrade" GroupName="InstallType" IsChecked="{Binding upgradeMode, Mode=TwoWay, Source={StaticResource modes}}" />
<RadioButton Checked="ChangeMode_Checked" Content="Change" x:Name="rbtnChange" GroupName="InstallType" IsChecked="{Binding changeMode, Mode=TwoWay, Source={StaticResource modes}}" />
</StackPanel>
</materialDesign:Card>
</StackPanel>
<StackPanel x:Name="StackMode" HorizontalAlignment="Center" VerticalAlignment="Center" Orientation="Horizontal" Visibility="Visible">
<materialDesign:Card Padding="32" Margin="16" Width="204" Height="147">
<StackPanel>
<TextBlock HorizontalAlignment="Left" Style="{DynamicResource MaterialDesignTitleTextBlock}" >Installation Mode</TextBlock>
<RadioButton Content="Default Settings" Name="rbtnDefaultMode" IsChecked="{Binding defaultMode, Source={StaticResource modes}, Mode=TwoWay}" Checked="defaultSettings_Checked"/>
<RadioButton Content="Custom Settings" Name="rbtnCustomMode" IsChecked="{Binding customMode, Source={StaticResource modes}, Mode=TwoWay}" Checked="customSettings_Checked"/>
</StackPanel>
</materialDesign:Card>
</StackPanel>
</Grid>
In this, I want to have it in a way so that if rbtnNew or rbtnUpgrade are selected, only then should the StackMode panel be should be visible. And if rbtnChange is selected, the panel StackMode panel should stay hidden.
You can add a custom style with a DataTrigger:
Remove the Visibility="Visible" from the StackMode panel.
Add a Setter that sets the default value of Visibility of the StackPanel to Visible.
Add a DataTrigger that sets its value to Collapsed (or Hidden) if the IsChecked value of rbtnChange is true. You can refer to the element with ElementName in the binding.
<Grid Background="#F8FBFD">
<StackPanel x:Name="StackType" HorizontalAlignment="Center" Orientation="Horizontal" Margin="0,93,0,428">
<materialDesign:Card Padding="32" Margin="16">
<StackPanel>
<TextBlock HorizontalAlignment="Left" Style="{DynamicResource MaterialDesignTitleTextBlock}" >Installation Type</TextBlock>
<RadioButton Checked="NewMode_Checked" Content="New " x:Name="rbtnNew" GroupName="InstallType" IsChecked="{Binding newMode, Mode=TwoWay, Source={StaticResource modes}}"/>
<RadioButton Checked="UpgradeMode_Checked" Content="Update" x:Name="rbtnUpgrade" GroupName="InstallType" IsChecked="{Binding upgradeMode, Mode=TwoWay, Source={StaticResource modes}}" />
<RadioButton Checked="ChangeMode_Checked" Content="Change" x:Name="rbtnChange" GroupName="InstallType" IsChecked="{Binding changeMode, Mode=TwoWay, Source={StaticResource modes}}" />
</StackPanel>
</materialDesign:Card>
</StackPanel>
<StackPanel x:Name="StackMode" HorizontalAlignment="Center" VerticalAlignment="Center" Orientation="Horizontal">
<materialDesign:Card Padding="32" Margin="16" Width="204" Height="147">
<StackPanel>
<TextBlock HorizontalAlignment="Left" Style="{DynamicResource MaterialDesignTitleTextBlock}" >Installation Mode</TextBlock>
<RadioButton Content="Default Settings" Name="rbtnDefaultMode" IsChecked="{Binding defaultMode, Source={StaticResource modes}, Mode=TwoWay}" Checked="defaultSettings_Checked"/>
<RadioButton Content="Custom Settings" Name="rbtnCustomMode" IsChecked="{Binding customMode, Source={StaticResource modes}, Mode=TwoWay}" Checked="customSettings_Checked"/>
</StackPanel>
</materialDesign:Card>
<StackPanel.Style>
<Style TargetType="{x:Type StackPanel}">
<Setter Property="Visibility" Value="Visible"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked, ElementName=rbtnChange}" Value="True">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
</StackPanel>
</Grid>
Another option is to use the built-in BooleanToVisibilityConverter converter.
<Grid Background="#F8FBFD">
<Grid.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
</Grid.Resources>
<StackPanel x:Name="StackType" HorizontalAlignment="Center" Orientation="Horizontal" Margin="0,93,0,428">
<materialDesign:Card Padding="32" Margin="16">
<StackPanel>
<TextBlock HorizontalAlignment="Left" Style="{DynamicResource MaterialDesignTitleTextBlock}" >Installation Type</TextBlock>
<RadioButton Checked="NewMode_Checked" Content="New " x:Name="rbtnNew" GroupName="InstallType" IsChecked="{Binding newMode, Mode=TwoWay, Source={StaticResource modes}}"/>
<RadioButton Checked="UpgradeMode_Checked" Content="Update" x:Name="rbtnUpgrade" GroupName="InstallType" IsChecked="{Binding upgradeMode, Mode=TwoWay, Source={StaticResource modes}}" />
<RadioButton Checked="ChangeMode_Checked" Content="Change" x:Name="rbtnChange" GroupName="InstallType" IsChecked="{Binding changeMode, Mode=TwoWay, Source={StaticResource modes}}" />
</StackPanel>
</materialDesign:Card>
</StackPanel>
<StackPanel x:Name="StackMode" HorizontalAlignment="Center" VerticalAlignment="Center" Orientation="Horizontal" Visibility="{Binding IsChecked, ElementName=rbtnChange, Converter={StaticResource BooleanToVisibilityConverter}}">
<materialDesign:Card Padding="32" Margin="16" Width="204" Height="147">
<StackPanel>
<TextBlock HorizontalAlignment="Left" Style="{DynamicResource MaterialDesignTitleTextBlock}" >Installation Mode</TextBlock>
<RadioButton Content="Default Settings" Name="rbtnDefaultMode" IsChecked="{Binding defaultMode, Source={StaticResource modes}, Mode=TwoWay}" Checked="defaultSettings_Checked"/>
<RadioButton Content="Custom Settings" Name="rbtnCustomMode" IsChecked="{Binding customMode, Source={StaticResource modes}, Mode=TwoWay}" Checked="customSettings_Checked"/>
</StackPanel>
</materialDesign:Card>
</StackPanel>
</Grid>
Update for your comment about the initial state that should be Collapsed. You can just add another DataTrigger for the IsChecked="False" state of the rbtnChange RadioButton.
<Style TargetType="{x:Type StackPanel}">
<Setter Property="Visibility" Value="Visible"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked, ElementName=rbtnChange}" Value="False">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsChecked, ElementName=rbtnChange}" Value="True">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
Of course, you could also "invert" the style, setting Collapsed as default and adding triggers for each of the other RadioButtons to set Visible, but for more buttons this would not scale well.

Use single Template for multiple Item Sources and render separate combobox in UI

I am new to WPF/XAML so I am stuck in one problem is it possible that if I create one TEMPLATE of combobox in UI and what if is it possible to use one ComboBox to render multi-item sources? For example, I have two item sources A and B and in XAML I have one common template. So is it possible that I can create two different ComboBox in UI for A and B from single template?
I am using below template for creation
<ComboBox x:Name="comboboxtemplate" ItemsSource="{Binding CboItemsource}" SelectedItem="{Binding comboboxSelecteditem, Mode=TwoWay}"
Visibility="{Binding ShowCombobox, UpdateSourceTrigger=PropertyChanged}" Width="{Binding ComboboxWidth, UpdateSourceTrigger=PropertyChanged}"
IsEnabled="{Binding FieldValueIsEditable, UpdateSourceTrigger=PropertyChanged}"
IsTextSearchCaseSensitive="False"
IsTextSearchEnabled="True"
TextSearch.TextPath="Description">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Code}" Width="0"/>
<TextBlock Text= "{Binding Description}" TextWrapping="Wrap" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
You could create a style that you apply to both ComboBoxes, .e.g.:
<Window x:Class="WpfApplication1.Window1"
...>
<Window.Resources>
<Style x:Key="cmbStyle" TargetType="ComboBox">
<Setter Property="Visibility" Value="{Binding ShowCombobox, UpdateSourceTrigger=PropertyChanged}" />
<Setter Property="IsEnabled" Value="{Binding FieldValueIsEditable, UpdateSourceTrigger=PropertyChanged}" />
<Setter Property="IsTextSearchEnabled" Value="True" />
<!-- ... -->
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Code}" Width="0"/>
<TextBlock Text= "{Binding Description}" TextWrapping="Wrap" />
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<StackPanel>
<ComboBox x:Name="cmb1" ItemsSource="{Binding CboItemsource}"
SelectedItem="{Binding comboboxSelecteditem, Mode=TwoWay}"
Style="{StaticResource cmbStyle}" />
<ComboBox x:Name="cmb2" ItemsSource="{Binding OtherItemsource}"
SelectedItem="{Binding OtherSelecteditem, Mode=TwoWay}"
Style="{StaticResource cmbStyle}" />
</StackPanel>
</Window>

WPF Add more interaction to listview items

I am binding my listview to a viewmodel using Caliburn. My view's code is the following:
<ListView x:Name="ListView" Grid.Row="1" Grid.ColumnSpan="2" ItemsSource="{Binding ProjectsPMod}" Margin="110,0,110,131" HorizontalContentAlignment="Stretch" BorderThickness="0" Height="111" VerticalAlignment="Bottom">
<interactivity:Interaction.Triggers>
<interactivity:EventTrigger EventName="SelectionChanged">
<cal:ActionMessage MethodName="OpenProjectShell">
<cal:Parameter Value="{Binding ElementName=ListView, Path=SelectedItem}" />
</cal:ActionMessage>
</interactivity:EventTrigger>
</interactivity:Interaction.Triggers>
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel>
<StackPanel Orientation="Horizontal">
<ContentControl Content="{StaticResource Appbar_Suitcase}" />
<Label Content="{Binding Name}"/>
</StackPanel>
<Separator HorizontalAlignment="Stretch" Margin="0, 10, 0, 0"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Right now each item in every row just displays its name and a briefcase icon. If I wanted to add an "Edit"further down that row, where if you clicked on it something happened (perhaps a popup appears), how would I do it?
You can make an ordinary Button look like a link using a template. Just add a Button to your StackPanel and bind it to a command:
<ListView x:Name="ListView" Grid.Row="1" Grid.ColumnSpan="2" ItemsSource="{Binding ProjectsPMod}" Margin="110,0,110,131" HorizontalContentAlignment="Stretch" BorderThickness="0" Height="111" VerticalAlignment="Bottom">
<interactivity:Interaction.Triggers>
<interactivity:EventTrigger EventName="SelectionChanged">
<cal:ActionMessage MethodName="OpenProjectShell">
<cal:Parameter Value="{Binding ElementName=ListView, Path=SelectedItem}" />
</cal:ActionMessage>
</interactivity:EventTrigger>
</interactivity:Interaction.Triggers>
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel>
<StackPanel Orientation="Horizontal">
<ContentControl Content="{StaticResource Appbar_Suitcase}" />
<Label Content="{Binding Name}"/>
</StackPanel>
<Separator HorizontalAlignment="Stretch" Margin="0, 10, 0, 0"/>
<Button Margin="0 10 0 0" Content="Link" Cursor="Hand" Command="{Binding YourCommand}">
<Button.Template>
<ControlTemplate TargetType="Button">
<TextBlock TextDecorations="Underline">
<ContentPresenter />
</TextBlock>
</ControlTemplate>
</Button.Template>
<Button.Style>
<Style TargetType="Button">
<Setter Property="Foreground" Value="Blue" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
You can control the position of the Button within the StackPanel using its Margin property.
If you mean "How to add an edit button for each row?" then you simply need to add a button in the ItemTemplate:
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel>
<StackPanel Orientation="Horizontal">
<ContentControl Content="{StaticResource Appbar_Suitcase}" />
<Label Content="{Binding Name}"/>
<!-- Edit button -->
<Button Command="{Binding EditCommandOnViewModel}" Content="Edit" />
</StackPanel>
<Separator HorizontalAlignment="Stretch" Margin="0, 10, 0, 0"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>

image binding to the drodown values in wpf

In my xaml form i have a dropdown button the dropdown values will bind from database and my requirement is i want to add one image for each dropdown value in the dropdown box, how can get this.....
<ctrl:DropDownButton Grid.Column="1"
Height="25"
Text="Add Question"
Width="125"
Margin="5,0,10,0">
<ctrl:DropDownButton.DropDownContextMenu>
<ContextMenu ItemsSource="{Binding Source={StaticResource QuestionTypes}}">
<ContextMenu.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Background="WhiteSmoke"/>
</ItemsPanelTemplate>
</ContextMenu.ItemsPanel>
<ContextMenu.ItemContainerStyle>
<Style TargetType="MenuItem">
<Setter Property="Command" Value="{Binding DataContext.AddQuestionCommand,
RelativeSource={RelativeSource AncestorType=UserControl}}" />
<Setter Property="CommandParameter" Value="{Binding}" />
</Style>
</ContextMenu.ItemContainerStyle>
<ContextMenu.ItemTemplate>
<DataTemplate>
<Grid Margin="-20,0,-50,0">
<TextBlock Grid.Column="1" Text="{Binding Converter={StaticResource EnumDescriptionConverter}}"/>
</Grid>
</DataTemplate>
</ContextMenu.ItemTemplate>
</ContextMenu>
</ctrl:DropDownButton.DropDownContextMenu>
</ctrl:DropDownButton>
*I wrote this outside of VisualStudio so please check the syntax
you should add an Image element to your DataTempalte and using a converter for the enum value resolve the path to the image you would like to present.
<ContextMenu.ItemTemplate>
<DataTemplate>
<Grid Margin="-20,0,-50,0">
<Grid>
<Grid.ColumnDefenitions>
<ColumnDefenition />
<ColumnDefenition />
</Grid.ColumnDefenitions>
<Image Source="{Binding Path=., Converter={StaticResource EnumImageConverter}}" />
<TextBlock Grid.Column="1" Text="{Binding Path=., Converter={StaticResource EnumDescriptionConverter}}"/>
</Grid>
</DataTemplate>
</ContextMenu.ItemTemplate>

Categories