0

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

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

我已经解决了使用 ViewModel 动态加载 XAMLXamlReader但不确定如何将ScrewControls 与 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
            });
    }
4

1 回答 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 属性绑定到螺丝状态,ContentTemplate 绑定到当前项目(即从 XAML 加载的螺丝用户控件),这将提供一种更自然的方式将视图和模型绑定在一起.

于 2016-09-13T08:58:46.947 回答