MVVM,ViewModelLocator,基于属性动态显示View with ViewModel

时间:2013-12-03 18:12:30

标签: c# wpf mvvm ivalueconverter viewmodellocator

enter image description here我有一个设计问题。请查看附图以了解应用程序设计。 基本上我只需要帮助找到正确的方法。

我有一个View和ViewModel,它包含一个TileUserControl。 它需要一组瓷砖,并以定义的尺寸,颜色,顺序等显示它们。它还能够将故事分组,并允许用户添加和删除Tiles。

Tile对象看起来像这样。

    public class Tile
    {
        public int ID { get; set; }
        public string View { get; set; }
        public List<string> Views { get; set; }
        public string TileSize { get; set; }

    }

到目前为止一切都很好。一切正常。

所有瓷砖都有内容。我想将内容设置为View和与Tile对象上的View字符串对应的ViewModel。

我正在使用MVVM Light,但也可能使用Caliburn Mico。 tile控件是WPF的DevExpress TileLayoutControl。

DevExpress TileLayoutControl doc

编辑:使用MainTilesView XAML更新

    <Grid>

        <dxlc:TileLayoutControl Padding="60,41,0,0"
                                ItemsSource="{Binding Tiles}" 
                                ScrollBars="None" 
                                ScrollViewer.VerticalScrollBarVisibility="Hidden" 
                                AllowGroupHeaderEditing="False" 
                                AllowMaximizedElementMoving="True" Background="{x:Null}">

            <dxlc:TileLayoutControl.GroupHeaderStyle>
                <Style TargetType="dxlc:TileGroupHeader">
                    <Setter Property="Foreground" Value="White"/>
                    <Setter Property="FontSize" Value="24"/>
                    <Setter Property="FontFamily" Value="Segeo UI"/>
                    <Setter Property="FontWeight" Value="Light"/>
                </Style>
            </dxlc:TileLayoutControl.GroupHeaderStyle>

            <dxlc:TileLayoutControl.ItemTemplate>
                <DataTemplate>
                    <dxlc:Tile Header="{Binding Header}" 
                               Size="{Binding TileSize}" 
                               dxlc:TileLayoutControl.GroupHeader="{Binding GroupHeader}" 
                               Tag="{Binding ID}"  
                               dxlc:FlowLayoutControl.IsFlowBreak="{Binding IsNewGroup}" 
                               Background="{Binding BackgroundColor}">
                    </dxlc:Tile>
                </DataTemplate>
            </dxlc:TileLayoutControl.ItemTemplate>

            <dxlc:TileLayoutControl.Resources>
                <conv:IsUserControlConverter x:Key="IsUserControlConverter"/>
                <conv:StringToTileConverter x:Key="StringToTileConverter"/>
                <Style TargetType="{x:Type dxlc:Tile}">
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding Path=TileSize}" Value="ExtraSmall">
                            <Setter Property="Size" Value="ExtraSmall"/>
                        </DataTrigger>
                        <DataTrigger Binding="{Binding Path=TileSize}" Value="1x1">
                            <Setter Property="Size" Value="ExtraSmall"/>
                        </DataTrigger>
                        <DataTrigger Binding="{Binding Path=TileSize}" Value="1x1">
                            <Setter Property="Size" Value="Small"/>
                            <Setter Property="Width" Value="150"/>
                            <Setter Property="Height" Value="150"/>
                        </DataTrigger>
                        <DataTrigger Binding="{Binding Path=TileSize}"  Value="1x2">
                            <Setter Property="Size" Value="Large"/>
                        </DataTrigger>
                        <DataTrigger Binding="{Binding Path=TileSize}"  Value="2x1">
                            <Setter Property="Size" Value="ExtraLarge"/>
                            <Setter Property="Width" Value="150"/>
                            <Setter Property="Height" Value="310"/>
                        </DataTrigger>
                        <DataTrigger Binding="{Binding Path=TileSize}"  Value="2x2">
                            <Setter Property="Size" Value="ExtraLarge"/>
                        </DataTrigger>
                        <DataTrigger Binding="{Binding Path=TileSize}"  Value="2x3">
                            <Setter Property="Size" Value="ExtraLarge"/>
                            <Setter Property="Width" Value="310"/>
                            <Setter Property="Height" Value="470"/>
                        </DataTrigger>
                        <DataTrigger Binding="{Binding Path=TileSize}"  Value="3x2">
                            <Setter Property="Size" Value="ExtraLarge"/>
                            <Setter Property="Width" Value="470"/>
                            <Setter Property="Height" Value="310"/>
                        </DataTrigger>
                        <DataTrigger Binding="{Binding Path=TileSize}"  Value="3x3">
                            <Setter Property="Size" Value="ExtraLarge"/>
                            <Setter Property="Width" Value="470"/>
                            <Setter Property="Height" Value="470"/>
                        </DataTrigger>
                        <DataTrigger Binding="{Binding Path=TileSize}"  Value="4x2">
                            <Setter Property="Size" Value="ExtraLarge"/>
                            <Setter Property="Width" Value="630"/>
                            <Setter Property="Height" Value="310"/>
                        </DataTrigger>
                        <DataTrigger Binding="{Binding Path=TileSize}"  Value="4x3">
                            <Setter Property="Size" Value="ExtraLarge"/>
                            <Setter Property="Width" Value="630"/>
                            <Setter Property="Height" Value="470"/>
                        </DataTrigger>
                        <DataTrigger Binding="{Binding Path=TileSize}"  Value="4x4">
                            <Setter Property="Size" Value="ExtraLarge"/>
                            <Setter Property="Width" Value="630"/>
                            <Setter Property="Height" Value="630"/>
                        </DataTrigger>
                        <DataTrigger Binding="{Binding Path=TileSize}"  Value="Single_1x1">
                            <Setter Property="Size" Value="Large"/>
                            <Setter Property="Width" Value="150"/>
                            <Setter Property="Height" Value="150"/>
                        </DataTrigger>



                        <DataTrigger Binding="{Binding Path=View,Converter={StaticResource IsUserControlConverter}}" Value="true">
                            <Setter Property="ContentTemplate">
                                <Setter.Value>
                                    <DataTemplate>
                                        <ContentControl cal:View.Model="{Binding Path=View, Converter={StaticResource StringToTileConverter}, UpdateSourceTrigger=Explicit}"/>                                        
                                    </DataTemplate>
                                </Setter.Value>
                            </Setter>
                        </DataTrigger>

                    </Style.Triggers>
                </Style>
            </dxlc:TileLayoutControl.Resources>

        </dxlc:TileLayoutControl>
    </Grid>

我的问题是如何将Tile.View中的UserControl加载到Tile内容中。 我已经使用DataTrigger和DataTemplate进行了上述操作。

StringToTileConverter just返回ViewModel的名称。

目前正在使用Caliburn Micro,我的绑定在模板部分之外工作得很好,但我不能让它们与DataTemplate一起使用。

此外,所有这些代码都不是很干净,所以我问是否有人有更干净的方法来做这件事。

1 个答案:

答案 0 :(得分:0)

当您使用Caliburn.Micro时,您可以利用其内置的 ViewLocator 。您不需要转换器或DataTriggers,因为您可以按如下方式定义DataTemplate:

  <DataTemplate>
    <ContentControl Width="100" Height="100" cal:View.Model="{Binding}" />
  </DataTemplate>

您可能会发现这有用:Binding ListBox to a collection of screens (widgets)

如果您需要更多示例,请告诉我。