0

ダイアグラム (カスタム UserControl を含む XAML ScrewControl) を動的に読み込む必要があります。

ViewModel クラスの依存関係プロパティ ( Status)をバインドする方法を検討しています。ScrewControl課題は、ダイアグラムにさまざまな数の が含まれる可能性がありScrewControl、それぞれが 内のディクショナリまたはコレクションにデータ バインドされる必要があることViewModelです。

XAML を動的に読み込むという最初の課題を解決しましたが、ViewModel の Collection/dictionary に sXamlReaderをバインドする方法がわかりません。ScrewControl

モデル クラスを表示

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 らしいかもしれませんが。その後、ItemTemplate を、ScrewStatus にバインドされた Content プロパティと ContentTemplate が現在のアイテム (つまり、XAML から読み込まれたスクリュー ユーザー コントロール) にバインドされた ContentControl になるように設定できます。これにより、ビューとモデルをバインドするより自然な方法が提供されます。 .

于 2016-09-13T08:58:46.947 に答える