WPF Binding Combobox具有不同的List和不同的SelectedValue

时间:2013-08-28 16:46:07

标签: c# wpf exception binding combobox

在我的UserControl ucStep2中,我有Step2InfoData对象的DataContext,它具有以下几个属性:

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

在我的应用程序中,我需要使用不同的常规测量类型绑定几个组合,例如{kg / m3,gm / m3},{meter,cm}等等这些测量组。我的意思是,多个组合可以列出相同的项目。所以我更喜欢创建可以在多个组合中使用的类列表。我创建了ComboItems.cs,其中包含填充下拉列表所需的所有项目列表。

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即ucStep2查看

<!-- 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>

我想从KgGmItems类中显示ObservableCllection KgGmList项,并将所选值绑定到绑定到此UserControl的类Step2InfoData的RockDensity_Unit。

在上面的组合中,我可以显示下拉菜单中的所有项目,默认情况下也会选择第一项。但是这个值并没有绑定到RockDensity_Unit;它的值仍为空。

我希望双向发生这种情况,即当以编程方式设置RockDensity_Unit proeprtiy的值时,应在下拉列表中选择该值。当然,值应该存在于列表中。

默认情况下,应选择第一项。

更新 在ucStep2.xaml.cs中添加了DependencyProperty

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>

错误

  

错误1类型引用找不到名为“ucStep2”的公共类型。第74行位置194.这是指组合框“,”   在FindAncestor之后

DOUBT Step2InfoData中的RockDensity_Unit CLR属性未受影响。

为什么代码无法找到ucStep2?仅供参考,我认为这可能是相关的:

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

2 个答案:

答案 0 :(得分: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 }
    };
}

答案 1 :(得分:1)

好的,让我们让这个绑定工作......首先,我使用KgGmItems类中的一个项目绑定到ComboBox。在这个类中,您有一组string值显示在下拉列表中,string属性绑定到ComboBox.SelectedItem ...完美!现在我假设你在名为Resources的{​​{1}}部分中有一个这个类的实例...让我们保持简单开头:

KgGmObj

这就是您在<ComboBox DataContext="{StaticResource KgGmObj}" ItemsSource="{Binding KgGmList}" SelectedItem="{Binding ValueSelected, Mode=TwoWay}" /> 和您的班级之间设置绑定所需的全部内容。但有一点需要注意的是,当您尝试从代码中设置所选项目时,如果将其设置为集合中的某个实际项目,它将工作...我认为使用ComboBox时这并不重要,但无论如何都要知道这一点很重要。如果您将自定义类设置为string中的对象类型,则可以设置所选项目,如下所示:

ComboBox

如果你有一个独特的可识别财产,那就更好了:

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

使用ValueSelected = KgGmList.Where(item => item.Id == Id).Single() 值,您应该能够从以下代码中设置所选项目:

string

更新&gt;&gt;&gt;好吧,让我们再来一次......我可能现在有足够的信息继续下去。我想你想要这样的东西:

ValueSelected = "Some value";

问题在于您已将<ComboBox DataContext="{StaticResource KgGmObj}" ItemsSource="{Binding KgGmList}" SelectedItem="{Binding RockDensity_Unit, Mode=TwoWay}" /> 的{​​{1}}设置为DataContext个对象。这意味着框架将尝试在该对象中找到名为ComboBox 的属性。我还看到了你对这个属性的定义中的另一个潜在问题。

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

接下来,我们必须从xaml中的RockDensity_Unit找到该属性的方法...我们可以使用DependencyProperty这样的绑定来实现:

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,那么这一切都可以工作......让我知道怎么回事。

更新2&gt;&gt;&gt;

您的错误是因为您必须在XAML文件的顶部添加XML命名空间......如下所示:

UserControl

然后你用它来引用你的类:

ucStep2

此外,在您的xmlns:YourNamespace="clr-namespace:ApplicationName.FolderNameContainingClass" 声明中,您应该提供您的控件的类型,而不是...AncestorType={x:Type YourNamespace:ucStep2} ... ,因此请更改

DependencyProperty

UserControl

显然......将'NameOfYourUserControl'替换为扩展Register("RockDensity_Unit", typeof(string), typeof(UserControl), 的类的实际名称。