具有不同列表和不同选定值的 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">
好的,让我们让这个绑定工作...首先,我正在使用您的 KgGmItems
类中的项目绑定到ComboBox
。在此类中,您有一个要在下拉列表中显示的string
值的集合,以及要绑定到ComboBox.SelectedItem
的string
属性...完善!现在我假设您在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}" />
这样做的问题是您已将ComboBox
的DataContext
设置为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 }
};
}