我需要动态加载图表(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"}
答案 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加载的螺旋用户控件),这将提供一种更自然的方式将视图和模型绑定在一起