具有不同列表和不同选定值的 WPF 绑定组合框

本文关键字:WPF 绑定 组合 列表 | 更新日期: 2023-09-27 18:29:33

在我的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}等此类测量组。我的意思是,多个组合都有相同项目的列表。所以我更喜欢创建此类列表的类,我可以在多个组合中使用。我创建了组合项.cs其中包含填充下拉列表所需的所有项列表。

组合项目.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 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>
我想显示来自 KgGmItems 类的

ObservableCllection KgGmList 项,并将所选值绑定到绑定到此用户控件的类 Step2InfoData 的RockDensity_Unit。

在上面的组合中,我能够在下拉列表中显示所有项目,默认情况下也选择了第一个项目。但该值不绑定到RockDensity_Unit;它的值保持为空。

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

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

更新在 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>

错误

错误 1 类型引用找不到名为"ucStep2"的公共类型。74号线位置194。 这是指组合框", " 在《寻找祖先》之后

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

具有不同列表和不同选定值的 WPF 绑定组合框

好的,让我们让这个绑定工作...首先,我正在使用您的 KgGmItems 类中的项目绑定到ComboBox。在此类中,您有一个要在下拉列表中显示的string值的集合,以及要绑定到ComboBox.SelectedItemstring属性...完善!现在我假设您在Resources部分中有一个名为 KgGmObj 的此类实例......让我们保持简单开始:

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

这就是设置ComboBox和类之间的绑定所需的全部内容。但需要注意的一点是,当您尝试从代码中设置所选项时,仅当您将其设置为集合中的实际项之一时,它才会起作用......我认为这在使用 string s 时并不算数,但无论如何了解这一点很重要。如果要将自定义类设置为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}" />

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

为了从UserControl xaml绑定到其代码隐藏,您需要使用DependencyProperty。您可以从 MSDN 的"依赖项属性概述"页了解如何实现这些内容。因此,首先,我建议您将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}" />

现在,如果您有要绑定到 SelectedItem 属性的DependencyProperty,并且您的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的类的实际名称。

使用字典。

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 }
    };
}