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

3

这里输入图片描述我有一个设计问题,请看一下附图,以获取应用程序设计的想法。 基本上,我只需要在这里找到正确的方法。

我有一个View和ViewModel,它们包含一个TileUserControl。 它接受一组瓷砖,并以定义的大小、颜色、顺序等显示它们。它还能够将瓷砖分组,并允许用户添加和删除瓷砖。

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; }

    }

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

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

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

DevExpress TileLayoutControl文档

编辑:附有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只返回ViewModel的名称。

目前正在使用Caliburn Micro,我的绑定在模板部分外部工作良好,但我无法使它们与DataTemplate一起工作。

此外,所有这些代码都不太干净,因此我想问是否有更清洁的方法来解决这个问题。


3
好的画作 :) 你有尝试过任何东西吗?你可以发布一下你已经完成的部分,还是你让我们帮你完成这个呢? :) - dev hedgehog
1
抱歉,我不确定你的问题是什么...你是在寻求有关使用MVVM框架实现这种设计的建议吗? - Oscar Mateu
确保您查看DataTemplateSelector。您可以创建任何逻辑以返回每个Tile对象的正确视图。 - eoldre
你说的"My issue is how to get the UserControl from Tile.View loaded into the Tile content."是什么意思?你能把这个问题分开并且解释清楚你想要做什么吗?Tile.View加载了什么?Tile content是什么?"getting"是什么意思?获取一个引用还是将其移动到其他地方?你的意思是什么? - G.Y
使用基于约定的方法来定位视图(例如按名称,因此TileViewModel期望在程序集中存在TileView),将具有视图的ViewModel绑定到ContentControl,并使用ViewLocator转换器自动加载适当的View。ContentControl Content="{Binding TileViewModel, Converter={StaticResource ViewLocator}}" /> - atomaras
显示剩余2条评论
1个回答

0

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

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

你可能会发现这个有用:将ListBox绑定到屏幕(小部件)集合
如果需要更详细的示例,请告诉我。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接