Remove elements from window based on Combobox selection xaml - c#

I have the following situation: inside xaml I get values from a database and fill the combobox..if the selected item in the combobox has a value "x" I want to hide some elements from the working window..thx for your tips
<TextBlock Text="XYZ:"/>
<ComboBox ItemsSource="{Binding DataContext.KeyLists.XYZ,
RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"
SelectedValuePath="XYZId"
SelectedValue="{Binding XYZId, Mode=TwoWay}"
DisplayMemberPath="Name" />

There are many ways to solve this.
you can make IValueConverter to convert selection values to Visibility, apply to each control with different converter parameter
you can write styles with triggers for the convtols
you could (not recommended) handle this in code

Related

How do I get a DataGridTemplateColumn to work with objects implementing the IEditable<T> interface?

I have a DataGrid with a DataGridComboBox column that works fine. It binds properly to the list of items, correctly displays the selected item, correctly selects an item, and binds the selected item's ID to the underlying row model properly.
It looks like this:
<DataGridComboBoxColumn
x:Name="AssetColumn"
Width="3*"
DisplayMemberPath="Item"
Header="Item"
ItemsSource="{Binding Data.AssetDescriptions, Source={StaticResource proxy}}"
SelectedValueBinding="{Binding AssetDescriptionID}"
SelectedValuePath="AssetDescriptionID" />
I'm trying to achieve the same thing with a DataGridTemplateColumn and an ordinary combo box. My effort:
<DataGridTemplateColumn Header="ItemTemplate" Width="3*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox
DisplayMemberPath="Item"
ItemsSource="{Binding Data.AssetDescriptions, Source={StaticResource proxy}}"
SelectedValue="{Binding AssetDescriptionID, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
SelectedValuePath="AssetDescriptionID" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
Unfortunately, this one doesn't respect the IEditable<T> interface that the Asset objects implement. Consequently, the usual editing mechanisms that you would normally have in a DataGrid, such as undo, will not work for this column.
Is there a way to write this in such a way that it works the way it's supposed to with the IEditable<T> interface?
Note: I am aware that I probably need a CellEditingTemplate to get this to work properly, but I'm not sure how to go about that. I can put the same combo box in the CellEditingTemplate as well, but I can't figure out how to get the column to switch over to editing mode once it receives the focus, and if I only put the combo box data template in the CellEditingTemplate, no data is displayed in the column.

combobox and listview binding issue wpf c#

I have a combobox which displays listview on dropdown, I am following MVVM Pattern and i have also set the public property in my Viewmodel and it works fine when i am assigning it to the Label but for Combobox it doesn't seem to rely on my binding. i tried numerous ways but unable to find the issue.
XAML :
<ComboBox Name="SearchBox" IsEditable="True" Background="White" md:HintAssist.Hint="Search MUID" Grid.Column="1" Margin="5 0 0 0"
Grid.Row="0" Height="40" Width="400" HorizontalContentAlignment="Left" HorizontalAlignment="Left" SelectedItem="{Binding ElementName=lstview ,Path=SelectedItem}" >
<ComboBoxItem>
<ListView x:Name="lstview" ItemsSource="{Binding filterSW}"
SelectedItem="{Binding SelectedMU}"
Height="200" ScrollViewer.VerticalScrollBarVisibility="Visible">
<ListView.View>
<GridView>
<GridViewColumn Width="130" Header="Mu-ID" />
<GridViewColumn Width="130" Header="MU-Identifier" DisplayMemberBinding="{Binding MU_Identifier}" />
<GridViewColumn Width="130" Header="Status" DisplayMemberBinding="{Binding RequestType}" />
<GridViewColumn Width="130" Header="UniqueID" />
</GridView>
</ListView.View>
</ListView>
</ComboBoxItem>
</ComboBox>
This works fine for me when i am using the public property and accessing its element , i also tried setting text={Binding SelectedMU.MU_Identifier} and selectedvalue but its just not working.
<Label Grid.Column="3" HorizontalAlignment="Center" Background="GreenYellow" Content="{Binding SelectedMU.MU_Identifier}"></Label>
It looks like you're trying to show a multi-column list in your ComboBox dropdown instead of the standard list where each item shows just a text line.
To achieve this effect you've placed a ListView inside the dropdown.
Unfortunately, this is just not going to work.
Both ComboBox and ListView descend from Selector which is an abstraction that allows to select an item from a list. This limits the property SelectedItem to one of the items that are contained in the list. If you try to assign to this property any value that it not in the list, the assignment is not going to work and the property will retain the value it had before you did the assignment.
Now, the list could either be specified right inside XAML or provided as a binding to property ItemsSource. You do the binding correctly for the ListView. But for the ComboBox you don't specify that binding. Instead you specify exactly one item of type ComboBoxItem which contains the whole ListBox as its value. So the only value that could be successfully assigned to the SelectedItem property of the ComboBox is that single ComboBoxItem. But your binding is never going to assign that value, that's why the ComboBox never shows anything when closed.
When it's open it does show the single item which contain the ListView but this is just an optical effect. The data binging is not going to work. The reason why it works for the Label is because the Label is not constrained and can show anything that the ListView tells it to show.
You can synchronize the ListView and the ComboBox only when both controls have the same bindings for both ItemsSource and SelectedItem properties. But in this case you won't be able to place the ListView inside the dropdown.
The closest you can get to what you want is by customizing the ComboBox's template as described in https://zamjad.wordpress.com/2012/08/15/multi-columns-combo-box, for example. What this won't give you compared to ListView is the column headers. Also, the columns will be evenly spaced inside the dropdown but this is what you have in your ListView anyway.
If you want to auto-size them, you'd need to add Width="Auto" SharedSizeGroup="cN" to each ColumnDefinition where "cN" should have the column number instead of N to make them unique within the Grid and add Grid.IsSharedSizeScope="True" to the <ComboBox >
That's a lot of trouble for something that one would expect to be much simpler, but, unfortunately, you cannot place a ListView inside the ComboBox's template, that's a limitation of how the base class Selector works with its items list.
There are other options if you are open to consider 3rd party control libraries. I worked with Syncfusion, they have SfMultiColumnDropDown which does what you want. I'm pretty sure other popular libraries have similar controls as well.

Binding WPF combobox to a user settings property

I've a combobox in WPF with 4 static values in it:
<ComboBox
SelectedValue="{Binding Source={x:Static properties:Settings.Default},
Path=KeyModifier, Mode=TwoWay}">
<ComboBoxItem>Alt</ComboBoxItem>
<ComboBoxItem>Shift</ComboBoxItem>
<ComboBoxItem>Ctrl</ComboBoxItem>
<ComboBoxItem>Win</ComboBoxItem>
</ComboBox>
I want to connect the selected value of this combobox with a simple string property in the user settings. That works half way: The selected value is perfectly written to Settings.Default.KeyModifier ... But after restarting the application the selected value of the combobox is not set ... despite that all other controls (Edits, Checkboxes) binded the same way on other properties are set correctly.
Is there some mystery on filling a combobox with values from a binded property?
Or do I have to do the whole selection process on startup manually in code behind?
Since you don't add strings, but ComboBoxItems to your ComboBox, you would also have to set its SelectedValuePath property:
<ComboBox SelectedValuePath="Content"
SelectedValue="{Binding Source={x:Static properties:Settings.Default},
Path=KeyModifier, Mode=TwoWay}">
<ComboBoxItem>Alt</ComboBoxItem>
<ComboBoxItem>Shift</ComboBoxItem>
<ComboBoxItem>Ctrl</ComboBoxItem>
<ComboBoxItem>Win</ComboBoxItem>
</ComboBox>
Alternatively add strings to the ComboBox, and use SelectedItem instead of SelectedValue:
xmlns:sys="clr-namespace:System;assembly=mscorlib"
...
<ComboBox SelectedItem="{Binding Source={x:Static properties:Settings.Default},
Path=KeyModifier, Mode=TwoWay}">
<sys:String>Alt</sys:String>
<sys:String>Shift</sys:String>
<sys:String>Ctrl</sys:String>
<sys:String>Win</sys:String>
</ComboBox>
Note also that since WPF 4.5 you may write the Binding like this:
SelectedItem="{Binding Path=(properties:Settings.Default).KeyModifier, Mode=TwoWay}"
Have you saved the settings after you change the values? Settings.Default.Save()

Mvvm wpf: update value binding before leaving focus of input element

I have this element in my xaml (DevExpress item):
<dxe:ComboBoxEdit IsTextEditable="False" EditValue="{Binding IDTIPOCONN}"
ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=Window},Path=DataContext.ttc}" />
All the binding are correct, and when I change the value, I trigger some event from my ViewModel.
My problem is the update of the value is executed only when I leave the focus of my comboBox. I need, instead, to execute my action when the value is changed, before leaving its foucs.
How can I do it? I need this because selecting one or another from the list, I show to the user some hidden elements.
Try for Binding set UpdateSourceTrigger=PropertyChanged:
<dxe:ComboBoxEdit IsTextEditable="False"
EditValue="{Binding Path=IDTIPOCONN, UpdateSourceTrigger=PropertyChanged}" ... />
In this case, most likely the default value of UpdateSourceTrigger is LostFocus.

ComboBox in DataGrid: ItemSource bound to dynamic resource, how to set default row?

I'm working in a C# project [for school], using WPF and implementing MVP. In this code, I've got a DataGrid showing a list of divers. The first column is the Name, and the second column shall show 'DivingType'. DivingType is a built in object, which has a property ID, such as 103A. There are about 400 of these, stored in a list, and each Diver ('row') has a Dives (List<Dive>) Property, and each of these Dives has a divingType property.
What we want to have, is that this column will by default show the DivingType.ID associated with the diver, but that the dropdown list shall contain ALL diving types, such that you shall be able to change it from there [and update the diver object]. To further complicate it, this is one of many views which we add to our window as UserControls.
With that said, here is the code. I've tried to cut out unnecessary clutter which I'm certain has no impact on the result.
<Window ...>
<Window.Resources>
<local:Presenter x:Key="myPresenter"/>
</Window.Resources>
<DockPanel DataContext="{StaticResource myPresenter}">
<UserControl ...>
<DataGrid ItemsSource="{Binding DiverList}" x:Name="datagrid">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Width="1*" Binding="{Binding Name}"/>
<DataGridTemplateColumn Header="Diving type" Width="1*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=UserControl},
Path=DataContext.DivingTypes}"
DisplayMemberPath="ID"
SelectedValue="{Binding Dives[0]}"
SelectedValuePath="divingType">
</ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</UserControl>
</DockPanel>
</Window>
When the program runs I get all DivingTypes.ID inside the combobox, but no selected value. The code does not put any related errors into the output window. I believe that what happens is that it calls DivingType.Equals but passing the DataContext for the row (the Diver) instead of the SelectedValuePath which I specify. Any way to override this behaviour inside XAML? Or is there an easier way to achieve this?
EDIT:
I've since edited the code posted above to be:
<ComboBox ItemsSource="{
Binding RelativeSource={
RelativeSource AncestorType=UserControl
},
Path=DataContext.DivingTypes
}"
SelectedValue="{
Binding Dives[0].divingType, Mode=TwoWay
}"
/>
This makes the correct value show in the combobox at the start, DivingType.ID is loaded from the Diver.Dives[0].divingType, but it still does not set the property when I select a new value in the dropdown box.
Use UpdateSourceTrigger=PropertyChanged.
Explanation here.
Have you tried to implemented INotifyPropertyChanged in your viewmodel and then raise the PropertyChanged event when the SelectedValue gets set.
If this is not working, can you set the SelectedValue
SelectedValue="{Binding Path=divingType, Mode=TwoWay}"

Categories

Resources