非XAML方式将数据绑定到集合/字典

时间:2016-09-13 06:38:16

标签: wpf dictionary mvvm data-binding programmatically

我需要动态加载图表(XAML包含自定义UserControl,ScrewControl)。

我正在研究从ViewModel类绑定Status的依赖项属性(ScrewControl)的方法。挑战是图表可能包含不同数量的ScrewControl,每个ViewModel s都需要与XamlReader中的字典或集合绑定数据。

我已经解决了使用ScrewControl动态加载XAML的第一个挑战,但不确定如何使用ViewModel中的Collection / dictionary绑定public class AssemblyViewModel { public Dictionary<int, ScrewStatus> Screws { get; set; } public FrameworkElement Image { get; set; } ... }

查看模型类

public partial class AssemblyView : UserControl
{
    private AssemblyViewModel viewModel;

    public AssemblyView(AssemblyViewModel viewModel)
    {
        InitializeComponent();
        DataContext = this.viewModel = viewModel;

        Loaded += OnLoaded;
    }

    public FrameworkElement XamlContent
    {
        get { return (FrameworkElement)GetValue(XamlContentProperty); }
        set { SetValue(XamlContentProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Content.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty XamlContentProperty =
        DependencyProperty.Register("XamlContent", typeof(FrameworkElement), typeof(AssemblyView), new PropertyMetadata(null, OnXamlChanged));

    private static void OnXamlChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args)
    {
        var view = dependencyObject as AssemblyView;
        var element = args.NewValue as FrameworkElement;
        if (null != element)
        {
            view.ContentControl.Children.RemoveRange(0, 1);
            view.ContentControl.Children.Add(element);

            var screws = element.FindChildren<Screw>();

            try
            {
                foreach (var screw in screws)
                {
                    // The ScrewControl has a name properties like "Screw_1", 1 is used as the key of the dictionary and Status as the Value
                    var parts = screw.Name.Split(new char[] { '_' }, StringSplitOptions.RemoveEmptyEntries);
                    if (2 == parts.Length)
                    {
                        BindingOperations.SetBinding(
                            screw,
                            Screw.ScrewStatusProperty,
                            new Binding(/*not sure what goes here*/)
                            {
                                Source = view.viewModel.Screws,
                            });
                    }
                }
            }
            catch (Exception e)
            {
                throw;
            }
        }
    }

    private void OnLoaded(object sender, RoutedEventArgs e)
    {

        // This works and loads the diagram 
        BindingOperations.SetBinding(
            this,
            XamlContentProperty,
            new Binding("Image")
            {
                Source = this.viewModel
            });
    }

查看课程

{"month": 9, "year": 2015, "name": "Mr A"}
{"month": 9, "year": 2015, "name": "Mr B"}
{"month": 10, "year": 2015, "name": "Mr B"}
{"month": 11, "year": 2016, "name": "Mr B"}

1 个答案:

答案 0 :(得分:0)

你快到了。这应该有效:

foreach (var screw in screws)
{
    // The ScrewControl has a name properties like "Screw_1", 1 is used as the key of the dictionary and Status as the Value
    var parts = screw.Name.Split(new char[] { '_' }, StringSplitOptions.RemoveEmptyEntries);
    if (2 == parts.Length)
    {
        BindingOperations.SetBinding(
            screw,
            Screw.ScrewStatusProperty,
            new Binding() // No need for a path as we're going to bind directly to the source value 
            {
                // The source of the databinding is the value of the Screws dictionary keyed by screw id (parsed from the screw name)
                Source = view.viewModel.Screws[(int)parts[1]],
            });
    }
}

尽管从XAML加载一个公共属性并将其作为ItemsControl的ItemsSource绑定,可能更多WPF'y。然后,您可以将ItemTemplate设置为ContentControl,其Content属性绑定到ScrewStatus,并且ContentTemplate绑定到当前项(即从XAML加载的螺旋用户控件),这将提供一种更自然的方式将视图和模型绑定在一起