WPF Binding Combox with different List and different SelectedValue

In my UserControl ucStep2, I have a DataContext object of a Step2InfoData object that has several properties along with:

private string rockDensUnit; public string RockDensity_Unit { get { return rockDensUnit; } set { if (rockDensUnit != value) { rockDensUnit = value; Changed("RockDensity_Unit"); } } } 

In my application, I had to bind several combos with various standard measurement types. Like {kg / m3, gm / m3}, {meter, cm}, etc. such groups of measures. I mean, several combos have a list of identical elements. Therefore, I preferred to create a class of such lists, which I can use in several combos. I created ComboItems.cs, which contains lists of all the elements that I will need to fill.

ComboItems.cs

 //**OBJECTS I USE FOR LIST OF IEMS** // Class for kg, gm public class KgGmItems { public ObservableCollection<string> KgGmList { get; set; } public KgGmItems() { KgGmList = new ObservableCollection<string>(); KgGmList.Add("kg/m3"); KgGmList.Add("gram/cm3"); } public string ValueSelected { get; set; } // Don't know if this is useful in my case } // Class for meter, cm public class MtCmItems : INotifyPropertyChanged { public MtCmItems() { Dict = new Dictionary<string, string> { {"meter", "meter"}, {"centimeter", "centimeter"} }; } //... } 

XML ie ucStep2 View

 <!-- As the objects KgGmItems doesn't contain in ucStep2.xaml.cs or Step2InfoData (that is bound to this UC) so add reference of those classes --> <UserControl.Resources> <ObjectDataProvider x:Key="KgGmObj" ObjectType="{x:Type top:KgGmItems}" /> <ObjectDataProvider x:Key="MtCmObj" ObjectType="{x:Type top:MtCmItems}" /> </UserControl.Resources> <ComboBox DataContext="{StaticResource KgGmObj}" ItemsSource="{Binding KgGmList}" SelectedValue="{Binding Path=RockDensity_Unit, Mode=TwoWay}" SelectedIndex="0" Background="#FFB7B39D" Grid.Row="5" Height="23" HorizontalAlignment="Left" Margin="401,61,0,0" Name="comboBox6" VerticalAlignment="Top" Width="84" Visibility="Hidden"> </ComboBox> 

I want to display the KgGmList ObservableCllection elements from the KgGmItems class and bind the selected value to the RockDensity_Unit of the Step2InfoData class bound to this UserControl.

In the combo above, I can display all the items in the drop-down list, also the 1st item is selected by default. But the value does not bind to RockDensity_Unit; this value remains equal to zero.

I want this to happen in 2 directions, that is, when the RockDensity_Unit software is set programmatically, the value should be selected in the drop-down list. Of course, the value must exist in the list.

By default, select the 1st item.

UPDATE Added by DependencyProperty to ucStep2.xaml.cs

 public static readonly DependencyProperty RockDensityUnitProperty = DependencyProperty.Register("RockDensity_Unit", typeof(string), typeof(UserControl), new FrameworkPropertyMetadata("kg/m3", FrameworkPropertyMetadataOptions.BindsTwoWayByDefault)); public string RockDensity_Unit { get { return this.GetValue(RockDensityUnitProperty) as string; } set { SetValue(RockDensityUnitProperty, value); } } 

XML

 <ComboBox DataContext="{StaticResource KgGmObj}" ItemsSource="{Binding KgGmList}" SelectedItem="{Binding Path=RockDensity_Unit, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ucStep2}}, Mode=TwoWay}" Background="#FFB7B39D" Grid.Row="5" Height="23" HorizontalAlignment="Left" Margin="401,61,0,0" Name="comboBox6" VerticalAlignment="Top" Width="84" Visibility="Hidden"> </ComboBox> 

ERROR

Error 1 A type reference cannot find an open type named 'ucStep2'. Line 74 Position 194. This refers to the calculation of "," after FindAncestor

Doubt The RockRensity_Unit CLR property in Step2InfoData is untouched.

Why can't the code find ucStep2? FYI, I think it might make a difference:

 <UserControl x:Class="WellBore.ucStep2" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:WellBore.Models" xmlns:top="clr-namespace:WellBore" mc:Ignorable="d" d:DesignHeight="870" d:DesignWidth="700" MaxHeight="970" MinHeight="700" MaxWidth="600"> 
0
source share
2 answers

Ok, so let this binding work ... first, I use an element from your KgGmItems class to bind to a ComboBox . In this class, you have a collection of string values โ€‹โ€‹to display in the drop-down list and string properties to bind to ComboBox.SelectedItem ... perfect! Now, I assume that you have an instance of this class in the Resources section called KgGmObj ... make it easier to start with:

 <ComboBox DataContext="{StaticResource KgGmObj}" ItemsSource="{Binding KgGmList}" SelectedItem="{Binding ValueSelected, Mode=TwoWay}" /> 

This is all you need to establish the binding between ComboBox and your class. However, it is worth noting that when you try to install the selected element from your code, it will work only if you set it to one of the actual elements in the collection ... I think that this does not really count when using string s, but itโ€™s important to know this anyway. If instead you configured your own class as an object type in ComboBox , you can set the selected item as follows:

 ValueSelected = KgGmList.Where(item => item.Name == "NameOfObjectToMatch").Single(); 

Or better, if you have a uniquely identifiable property:

 ValueSelected = KgGmList.Where(item => item.Id == Id).Single() 

With your string values, you should set the selected item from the code as follows:

 ValueSelected = "Some value"; 

UPDATE โ†’> Okay, so let it go again ... I think I can have enough information to continue. I think you want something like this:

 <ComboBox DataContext="{StaticResource KgGmObj}" ItemsSource="{Binding KgGmList}" SelectedItem="{Binding RockDensity_Unit, Mode=TwoWay}" /> 

The problem is that you installed the DataContext from ComboBox into your KgGmObj object. This means that the Framework will try to find a property named RockDensity_Unit in this object. I also see another potential problem in defining this property.

To link UserControl xaml with its code behind, you need to use DependencyProperty . You can find out how to implement them on the "Dependency Properties Overview" page on MSDN. So first, I would recommend implementing your RockDensity_Unit property as DependencyProperty .

Next, we need to find a way for this property from ComboBox to xaml ... we can do this using the RelativeSource binding as follows:

 <ComboBox DataContext="{StaticResource KgGmObj}" ItemsSource="{Binding KgGmList}" SelectedItem="{Binding RockDensity_Unit, RelativeSource={RelativeSource Mode= FindAncestor, AncestorType={x:Type ucStep2}}, Mode=TwoWay}" /> 

Now, if you have DependencyProperty to bind to the SelectedItem property and your UserControl class is ucStep2 , this should work all ... let me know how this happens.

UPDATE 2 โ†’>

Your mistake is that you need to add an XML namespace at the top of your XAML file ... something like this:

 xmlns:YourNamespace="clr-namespace:ApplicationName.FolderNameContainingClass" 

Then you use it to reference your class as follows:

 ...AncestorType={x:Type YourNamespace:ucStep2} ... 

Also, in the DependencyProperty declaration, you must specify the type name of your control, not UserControl , so change

 Register("RockDensity_Unit", typeof(string), typeof(UserControl), 

to

 Register("RockDensity_Unit", typeof(string), typeof(NameOfYourUserControl), 

Understood ... replace "NameOfYourUserControl" with the actual name of your class, which extends UserControl .

+1
source

Use a dictionary.

Xaml

 <ComboBox ItemsSource="{Binding Dict}" DisplayMemberPath="Value" SelectedValuePath="Key" SelectedValue="{Binding Prop}"/> 

Code for

 public Dictionary< ValueType, string > Dict { get; private set; } private ValueType _prop; public ValueType Prop { get{ return _prop } set { _prop = value; NotifyPropertyChanged( "Prop" ); // Implement INotifyPropertyChanged } } public ViewModel() { Dict = new Dictionary< ValueType, string >() { { value1, string1 }, { value2, string2 }, { value3, string3 } }; } 
+1
source

Source: https://habr.com/ru/post/1499597/


All Articles