In my UserControl ucStep2 I have DataContext of 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 app I got to bind several combo's with different normally measurement types Like {kg/m3, gm/m3}, {meter, cm} and so on such groups of measures. I mean, multiple combo's to have list of same items. So I preferred to create Class's of such lists that I can use in multiple combos. I created ComboItems.cs which contains all items lists that I will need to populate the drop down.
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 i.e. 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 ObservableCllection KgGmList items from KgGmItems class and bind the selected value to RockDensity_Unit of class Step2InfoData that is bound to this UserControl.
In the above combo, I am able to display all items in the drop down, also 1st item is selected by default. But the value is not bind to RockDensity_Unit; it's value remains null.
I want this to happen 2-way i.e. when RockDensity_Unit proeprtiy's value is set programmatically, the value should be selected in the drop down. Of course the value should exists in the list.
By default the 1st item should be selected.
UPDATE Added DependencyProperty in 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 The type reference cannot find a public type named 'ucStep2'. Line 74 Position 194. This refers to the combobox ", " after FindAncestor
DOUBT The RockDensity_Unit CLR property in Step2InfoData is untouched.
Why is the code not able to find ucStep2 ? FYI, I think this may be relevant :
<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">
Use a Dictionary.
XAML
Code Behind
Ok, so let's get this binding working... first, I am using an item from your
KgGmItems
class to bind to theComboBox
. In this class you have a collection ofstring
values to display in the drop down and astring
property to bind to theComboBox.SelectedItem
... perfect! Now I'm assuming that you have an instance of this class in theResources
section calledKgGmObj
... let's keep it simple to start with:This is all you need to setup the binding between the
ComboBox
and your class. One thing to note though, is that when you try to set the selected item from your code, it will only work if you set it to one of the actual items in the collection... I think that this doesn't really count when usingstring
s, but it's important to know this anyway. If you were setting a custom class as the type of objects in theComboBox
instead, then you could set the selected item like this:Or better like this if you had a uniquely identifiable property:
With your
string
values, you should be able to set the selected item from code like this:UPDATE >>> Ok, so let's have another go... I think that I may have enough information to go on now. I think that you want something like this:
The problem with this is that you have set the
DataContext
of theComboBox
to yourKgGmObj
object. This means that the Framework is going to try to find a property namedRockDensity_Unit
in that object. I also see another potential problem in your definition of this property.In order to bind from a
UserControl
xaml to its code behind, you need to use aDependencyProperty
. You can find out how to implement these from the Dependency Properties Overview page at MSDN. So first, I would recommend that you implement yourRockDensity_Unit
property as aDependencyProperty
.Next, we have to find a way to that property from the
ComboBox
in the xaml... we can do that using aRelativeSource
binding like this:Now, if you have a
DependencyProperty
to bind to theSelectedItem
property and yourUserControl
class is nameducStep2
, this should all work... let me know how it goes.UPDATE 2 >>>
Your error is because you have to add an XML namespace at the top of your XAML file... something like this:
Then you use it to reference your class like this:
Also, in your
DependencyProperty
declaration, you're supposed to supply the name the type of your control, notUserControl
, so changeto
Clearly... replace 'NameOfYourUserControl' with the actual name of your class that extends the
UserControl
.