WPF UserControl与ItemsSource路径名属性,如ComboBox 'SelectedValu
本文关键字:ComboBox SelectedValu UserControl ItemsSource 路径名 属性 WPF | 更新日期: 2023-09-27 18:04:20
我有一个WPF UserControl包装ActiveX WinForms UserControl,所以我可以正确地利用MVVM/Bindings,而不必从视图模型操作UI。
我的UserControl有一个ItemsSource DependencyProperty(和其他的)。我现在想要的是实现一个"路径"属性在相同的方式,ComboBox有一个SelectedValuePath
或DisplayMemberPath
属性,以使其成为一个独立的模块。
XAML
<myControls:MyUserControl ItemsSource="{Binding ItemsSource}" Title.../>
相关后台代码public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register(ItemsSourcePropertyName, typeof(IEnumerable), typeof(MyControl), new PropertyMetadata(ItemsSourcePropertyChanged));
public const string ItemsSourcePropertyName = "ItemsSource";
public IEnumerable ItemsSource
{
get
{
return (IEnumerable)GetValue(ItemsSourceProperty);
}
set
{
SetValue(ItemsSourceProperty, value);
}
}
private static void ItemsSourcePropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
MyControl control = (MyControl)sender;
if (control != null)
{
control.PropertyChanged();
}
}
private void PropertyChanged()
{
if (ItemsSource is List<MyModel>) //TODO: figure out how to avoid this cast for user input fieldname for the path
{
List<MyModel> list = (List<MyModel>)ItemsSource;
if (m_axHost == null)
{
// Create the interop host control.
m_axHost = new System.Windows.Forms.Integration.WindowsFormsHost();
// Create the ActiveX control.
MyAxControl AXcontrol = new MyAxControl();
AXcontrol.SetData(list.Select(a=>a.XValue).ToArray(), list.Select(a=>a.YValue).ToArray(), Title, ...);
// Assign the ActiveX control as the host control's child.
m_axHost.Child = AXcontrol;
// Add the interop host control to the Grid
// control's collection of child controls.
this.axControlHolder.Children.Add(m_axHost);
}
else
{
MyAxControl AXcontrol = (MyAxControl)m_axHost.Child;
AXcontrol.ClearData();
control.SetData(list.Select(a=>a.XValue).ToArray(), list.Select(a=>a.YValue).ToArray(), Title, ...);
}
}
}
我想:
<myControls:MyUserControl ItemsSource="{Binding ItemsSource}" XValuePath="XPathname" YValuePath="YPathname" Title.../>
和
control.SetData(ItemsSource.Select(a=>a."XPathname").ToArray(), ItemsSource.Select(a=>a."YPathname").ToArray(), Title, ...);
我认为我必须使用反射,但我真的不知道如何前进。如何使用字符串路径名为UserControl生成正确的数据?
所有的Google/SO结果给了我解决我的ItemsSource问题(我没有)或我的DependencyProperty问题(再次,非常确定我的工作很好)的答案。我想通过在ItemsSource中使用用户指定的数据路径,使我的UserControl更加灵活,以便将来可用。
来自这个答案的反射技术为解决方案提供了基础:
var xValues = (from item in this.ItemsSource
let property = item.GetType().GetProperty(this.XValuesPath)
select property.GetValue(item)).ToArray();
var yValues = (from item in this.ItemsSource
let property = item.GetType().GetProperty(this.YValuesPath)
select property.GetValue(item)).ToArray();
,然后可以将其分配给ActiveX控件
control.SetData(xValues, yValues, Title, ...);
如果需要特定类型,例如double[]
或DateTime[]
,则可以在linq语句中进行强制转换:
DateTime[] xValues = (from item in this.ItemsSource
let property = item.GetType().GetProperty(this.XValuesPath)
select (DateTime)property.GetValue(item)).ToArray();
double[] yValues = (from item in this.ItemsSource
let property = item.GetType().GetProperty(this.YValuesPath)
select (double)property.GetValue(item)).ToArray();
检查角色转换需要更多的工作:
DateTime dt = new DateTime();
DateTime[] xValues = (from item in this.ItemsSource
let property = item.GetType().GetProperty(this.XValuesPath)
let value = property.GetValue(item)
let castOK = DateTime.TryParse(value.ToString(), out dt)
select castOK ? dt : _defaultDateTimeValue).ToArray();
double d = new double();
double[] yValues = (from item in this.ItemsSource
let property = item.GetType().GetProperty(this.YValuesPath)
let value = property.GetValue(item)
let castOK = double.TryParse(value.ToString(), out d)
select castOK ? d : _defaultDoubleValue).ToArray();