【发布时间】:2023-12-31 15:43:01
【问题描述】:
您好,我有一个应用程序设计问题,我家您可以帮我解决它.... 这是我在 silverlight 中的第一个应用程序,也是第一个使用 mvvm 设计模式的应用程序,我不确定我应该如何应用 mvvm..
该应用程序是一个动态应用程序,在运行时我可以添加/删除用户控件...
所以我有一个位于 MainWindowModel 后面的 MainWindowView。
MainWindowModel 有一个 Workspaces 列表,实际上是 WorkspaceModel 类...
我有多个用户控件,每个人都有自己的视图模型,女巫继承了 WorkspaceModel。
Workspaces 属性绑定到 MainWindowView 中的容器,因此向 Workspaces 列表添加新的 UserControlModel 会自动将该控件添加到视图中。 现在我的问题在哪里......我想让这个动态添加的用户控件进行交互。可以说一个用户控件是一棵树,一个是网格...我想要一种方法来说明 Grid UserControl 模型(WorkspaceModel)的 Itemsource 属性绑定到 Tree Usercontrol 模型(WorkspaceModel)中的 SelectedNode.Nodes 属性。
MainWindowModel 有一个属性名称 BindingEntries 女巫有一个 BindingEntry 列表... BindingEntry 存储绑定的源属性和目标属性,例如我的 workspacemodel_1.SelectedNode.Nodes -> workspacemodel_2.ItemSource...
或者作为一个变体,MainWindowView 有一个属性 ViewStateModel。这个 ViewStateModel 类具有动态创建的属性 - “注入”属性类型描述符/反射等......因此用户可以在运行时定义显示的用户控件(通过修改工作区列表)并可以定义视图模型(ViewStameModel)和绑定在工作空间模型属性和这个 ViewStateModel 属性之间......
所以我实际上想将 2 个视图模型彼此绑定... 怎么做? 创建观察者模式? 到目前为止的设计完全错误吗?
我希望这是有道理的.....
我会尝试添加一些示例代码...项目很大我将尝试仅将我在问题描述中提到的部分合并...希望我不会错过任何代码
首先
public class MainWindowModel : ModelBase
{
private ObservableCollection<WorkspaceModel> _workspaces;
private ModelBase _userViewModel;
public MainWindowModel()
{
base.DisplayName = "MainWindowModel";
ShowTreeView(1);
ShowTreeView(2);
ShowGridView(3);
ShowGridView(4);
UserViewModel = new ViewModel(); //this is the ViewStateModel
}
void ShowTreeView(int id)
{
WorkspaceModel workspace = ControlFactory.CreateModel("TreeControlModel", id);
this.Workspaces.Add(workspace);
OnPropertyChanged("Workspaces");
SelectedWorkspace = workspace;
}
void ShowGridView(int id)
{
WorkspaceModel workspace = ControlFactory.CreateModel("GridControlModel", id);
this.Workspaces.Add(workspace);
OnPropertyChanged("Workspaces");
SelectedWorkspace = workspace;
}
public ObservableCollection<WorkspaceModel> Workspaces
{
get
{
if (_workspaces == null)
{
_workspaces = new ObservableCollection<WorkspaceModel>();
}
return _workspaces;
}
}
public ModelBase UserViewModel
{
get
{
return _userViewModel;
}
set
{
if (_userViewModel == value)
{
return;
}
_userViewModel = value;
OnPropertyChanged("UserViewModel");
}
}
}
来自 MainappView 的 sn-ps
<DataTemplate x:Key="WorkspaceItemTemplate">
<Grid >
//workaround to use Type as in WPF
<Detail:DetailsViewSelector Content="{Binding}" TemplateType="{Binding}" >
<Detail:DetailsViewSelector.Resources>
<DataTemplate x:Key="TreeControlModel" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<TreeControl:TreeControlView />
</DataTemplate>
<DataTemplate x:Key="GridControlModel" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<GridControl:GridControlView />
</DataTemplate>
<DataTemplate x:Key="EmptyTemplate">
</DataTemplate>
</Detail:DetailsViewSelector.Resources>
</Detail:DetailsViewSelector>
</Grid>
</DataTemplate>
<DataTemplate x:Key="WorkspacesTemplate">
<ItemsControl IsTabStop="False" ItemsSource="{Binding}" ItemTemplate="{StaticResource WorkspaceItemTemplate}" Margin="6,2"/>
</DataTemplate>
</UserControl.Resources>
<toolkit:HeaderedContentControl Grid.Column="2" HorizontalAlignment="Stretch" Name="hccWorkspaces" VerticalAlignment="Top" Header="Workspaces" Content="{Binding Source={StaticResource vm}, Path=Workspaces}" ContentTemplate="{StaticResource WorkspacesTemplate}"/>
public class ControlFactory
{
public static WorkspaceModel CreateModel(string type, int id)
{
switch (type)
{
case "TreeControlModel": return new TreeControlModel() { Id=id}; break;
case "GridControlModel": return new GridControlModel() { Id = id }; break;
}
return null;
}
}
public class GridControlModel : WorkspaceModel
{
#region Fields
ObservableCollection<TreeItem> _items;
TreeItem _selectedItem;
#endregion // Fields
#region Constructor
public GridControlModel()
{
base.DisplayName = "GridControlModel";
}
#endregion // Constructor
#region Public Interface
public ObservableCollection<TreeItem> Items
{
get
{
return _items;
}
set
{
if (_items == value)
return;
_items = value;
OnPropertyChanged("Items");
}
}
public TreeItem SelectedItem
{
get
{
return _selectedItem;
}
set
{
if (_selectedItem.Equals(value))
{
return;
}
_selectedItem = value;
OnPropertyChanged("SelectedItem");
}
}
#endregion // Public Interface
#region Base Class Overrides
protected override void OnDispose()
{
this.OnDispose();
}
#endregion // Base Class Overrides
}
<Grid x:Name="LayoutRoot" Background="White">
<sdk:DataGrid Grid.Column="2" Grid.Row="1" HorizontalAlignment="Stretch" Name="dataGrid1" VerticalAlignment="Stretch" ItemsSource="{Binding Path=SelectedTreeNode.Children}" IsEnabled="{Binding}" AutoGenerateColumns="False">
<sdk:DataGrid.Columns>
<sdk:DataGridTextColumn CanUserReorder="True" CanUserResize="True" CanUserSort="True" Header="Id" Width="Auto" Binding="{Binding Id}" />
<sdk:DataGridTextColumn CanUserReorder="True" CanUserResize="True" CanUserSort="True" Header="Name" Width="Auto" Binding="{Binding Name}"/>
</sdk:DataGrid.Columns>
</sdk:DataGrid>
</Grid>
</UserControl>
【问题讨论】:
-
如果您不专注于将其融入书中的模式,您会过得更轻松吗?...我真的很好奇。
-
这么长的问题没人看,请尽量简短。
标签: c# silverlight design-patterns mvvm