如何使用MVVM模式在WPF中动态绑定UserControl

时间:2018-08-03 12:39:09

标签: c# wpf mvvm

当前,我正在使用WPF MVVM应用程序,在该应用程序中我想使用ItemsControl在MainWindow.xaml中显示UserControl。根据要求,我必须通过从ViewModel管理某些条件来切换或绑定不同的用户控件。正如我在下面的代码中提到的,应该在其中绑定UserControl。但是目前的问题是它的静态特性和完美的工作原理。但是我无法根据条件进行更改。那么,有什么可以在运行时从ViewModel更改UserControlColumn1XL的东西吗?预先感谢。

<StackPanel Grid.Column="0" Background="Black" VerticalAlignment="Top" >
            <ItemsControl ItemsSource="{Binding NormalCollection}" Name="ListNormal" Margin="4,0" >
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <WrapPanel HorizontalAlignment="Left" />
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <!--<This below line should be dynamically change through MVVM code>-->
                        <controls:UserControlColumn1XL HorizontalAlignment="Left" Margin="2" />
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
    </StackPanel>

2 个答案:

答案 0 :(得分:0)

这里是使用DataTemplateSelector ....

的示例

这里有一个简单的ViewModel

public class YourCustomObject : INotifyPropertyChanged
{
    public string YourProperty { get; set; }  // Remember to rise propertychanged

    public event PropertyChangedEventHandler PropertyChanged;
}


public class YourViewModel 
{
    public ObservableCollection<YourCustomObject> Objects { get; set; }
}

定义要使用的不同模板:

<ItemsControl ItemsSource="{Binding Objects}" Name="ListNormal" Margin="4,0">
    <ItemsControl.Resources>
        <DataTemplate x:Key="firstDataTemplate">
            <UserControl1 />
        </DataTemplate>

        <DataTemplate x:Key="otherDataTemplate">
            <UserControl2 />
        </DataTemplate>
    </ItemsControl.Resources>

创建一个继承自DataTemplateSelector的类:

 public class MySelector : DataTemplateSelector
{
    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        FrameworkElement element = container as FrameworkElement;

        if (element != null && item != null && item is YourCustomObject)
        {
            YourCustomObject taskitem = item as YourCustomObject;

            // HERE i'm putting the custom logic for choosing the correct template
            if (taskitem.YourProperty == "Value 1")
                return
                    element.FindResource("firstDataTemplate") as DataTemplate;
            else
                return
                    element.FindResource("otherDataTemplate") as DataTemplate;
        }

        return null;
    }
}

将选择器的一个实例添加到主视图:

<Window.Resources>
    <local:MySelector x:Key="Selector"/>
</Window.Resource>

ItemTemplateSelector的{​​{1}}属性设置为选择器:

ItemsControl

更多参考文献Here

答案 1 :(得分:0)

通常这样做的方法是使用DataTemplates。从ViewModel中的ObservableCollection<object> Objects开始...不一定是<object>,如果您愿意,它可以是一些常见的基类。然后在XAML中为每种类型添加DataTemplates。我将它们放置在ItemsControl.Resources中,但是您可以将它们放置在UserControl.Resources或您认为合适的其他位置:

<ItemsControl>
    <ItemsControl.Resources>

        <DataTemplate DataType="{x:Type viewmodels:YourViewModel1}">
            <views:UserControl1 />
        </DataTemplate>

        <DataTemplate DataType="{x:Type viewmodels:YourViewModel2}">
            <views:UserControl2 />
        </DataTemplate>

        ... etc ...

还删除<ItemsControl.ItemTemplate>标签,因为如果不这样做,它将覆盖数据模板。

这就是您需要做的!每次YourViewModel1中有一个类型为Objects的对象时,它将与UserControl1一起显示,并且对于所有其他指定模板,该对象也会再次显示。