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有一个SelectedValuePathDisplayMemberPath属性,以使其成为一个独立的模块。

目前:

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更加灵活,以便将来可用。

WPF UserControl与ItemsSource路径名属性,如ComboBox 'SelectedValu

来自这个答案的反射技术为解决方案提供了基础:

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();