2016-09-13 9 views
0

私は、カスタムUserControlを含むXAML(ScrewControl)の図を動的に読み込む必要があります。コレクション/辞書にデータバインドするためのXAML以外の方法

私はViewModelクラスからScrewControlの依存関係プロパティ(Status)をバインドする方法を検討しています。課題は、ScrewControlのさまざまな数を含むダイアグラムであり、それぞれがViewModelの辞書またはコレクションにバインドされたデータである必要があることです。 を使用してXAMLを動的に読み込むのは最初の課題ですが、ScrewControlをViewModelのCollection /辞書とバインドする方法はわかりません。

ビューモデルクラス

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 
      }); 
    } 
+1

これに答えるには、XamlとViewModelの最小限のバージョンを確認する必要があります –

答えて

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を、ScrewStatusにバインドされたContentプロパティと現在のアイテムにバインドされたContentTemplate(つまり、XAMLからロードされたスクリューユーザーコントロール)を持つContentControlに設定すると、ビューとモデルを結合するより自然な方法が提供されます。

関連する問題