0

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">
4

2 回答 2

1

好的,让我们让这个绑定工作......首先,我正在使用你KgGmItems班级中的一个项目来绑定到ComboBox. 在这个类中,您有一组string值要显示在下拉列表中,还有一个string属性要绑定到ComboBox.SelectedItem......完美!现在我假设您在Resources名为KgGmObj... 的部分中有一个此类的实例,让我们从简单开始:

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

这就是您设置ComboBox和您的类之间的绑定所需的全部内容。不过要注意的一件事是,当您尝试从代码中设置所选项目时,只有将其设置为集合中的实际项目之一时,它才会起作用......我认为这并不真正计算在内使用strings,但无论如何了解这一点很重要。如果您将自定义类设置为对象的类型ComboBox,那么您可以像这样设置所选项目:

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

或者如果你有一个唯一可识别的属性,最好这样:

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

使用您的string值,您应该能够从如下代码中设置所选项目:

ValueSelected = "Some value";

更新 >>> 好的,让我们再试一次……我我现在可能有足够的信息继续下去。我认为你想要这样的东西:

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

这样做的问题是您已将 of 设置DataContextComboBox您的KgGmObj对象。这意味着框架将尝试查找RockDensity_Unit 在该对象中命名的属性。我还在您对此属性的定义中看到了另一个潜在问题。

为了从UserControlxaml 绑定到其后面的代码,您需要使用DependencyProperty. 您可以从MSDN的Dependency Properties Overview页面了解如何实现这些。因此,首先,我建议您将RockDensity_Unit属性实现为DependencyProperty.

接下来,我们必须从 xaml 中找到该属性的方法ComboBox......我们可以使用RelativeSource如下绑定来做到这一点:

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

现在,如果你有一个DependencyProperty绑定到SelectedItem属性并且你的UserControl类被命名ucStep2,这应该都可以工作......让我知道它是怎么回事。

更新 2 >>>

您的错误是因为您必须在 XAML 文件的顶部添加一个 XML 命名空间......像这样:

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

然后你用它来引用你的类,如下所示:

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

此外,在您的DependencyProperty声明中,您应该提供控件类型的名称,而不是UserControl所以更改

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

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

显然...将“NameOfYourUserControl”替换为扩展UserControl.

于 2013-08-29T13:12:30.697 回答
1

使用字典。

XAML

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

代码背后

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 }
    };
}
于 2013-08-28T17:12:54.097 回答