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

问题描述 投票:0回答:1

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

ScrewControl
)。

我正在研究从 ViewModel 类绑定

Status
的依赖属性(
ScrewControl
)的方法。挑战在于图表可以包含不同数量的
ScrewControl
s,每个都需要数据绑定到
ViewModel
中的字典或集合。

我已经解决了使用

XamlReader
动态加载 XAML 的第一个挑战,但不确定如何将
ScrewControl
s 与来自 ViewModel 的集合/字典绑定。

查看模型类

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
            });
    }
wpf dictionary mvvm data-binding
1个回答
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 加载的螺丝用户控件),这将提供一种更自然的方式将视图和模型绑定在一起.

© www.soinside.com 2019 - 2024. All rights reserved.