Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/338.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在MVVM和WPF中将ViewModel转换为画布_C#_Wpf_Mvvm - Fatal编程技术网

C# 如何在MVVM和WPF中将ViewModel转换为画布

C# 如何在MVVM和WPF中将ViewModel转换为画布,c#,wpf,mvvm,C#,Wpf,Mvvm,我是WPF和MVVM的新手,希望您能帮助我解决以下问题 我想创建一个应用程序,在这个应用程序中,用户通过一个对话框指定如何在一个页面上布局N个图表对象,然后应用程序在画布上向他显示这个布局。当用户对画布中看到的布局感到满意时,会将其保留以供以后使用 所有图表对象都可以可视化为矩形。用户还可以定义一个标题,它也是一个矩形 典型的布局可能是页面顶部的标题,下面是三个并列的图表。用户可以在对话框中指定此布局以及每个子级的尺寸和位置,然后点击“应用”按钮,期望在画布上以图形形式看到此规范 在我的视图模型

我是WPF和MVVM的新手,希望您能帮助我解决以下问题

我想创建一个应用程序,在这个应用程序中,用户通过一个对话框指定如何在一个页面上布局N个图表对象,然后应用程序在画布上向他显示这个布局。当用户对画布中看到的布局感到满意时,会将其保留以供以后使用

所有图表对象都可以可视化为矩形。用户还可以定义一个标题,它也是一个矩形

典型的布局可能是页面顶部的标题,下面是三个并列的图表。用户可以在对话框中指定此布局以及每个子级的尺寸和位置,然后点击“应用”按钮,期望在画布上以图形形式看到此规范

在我的视图模型中,我将有一个树,其中父节点是画布,有一个子节点类型为header,三个子节点类型为chart

用户可能不喜欢所看到的内容,并在对话框中进行更改,从而影响视图模型中的更改


我有点理解对话框和视图模型之间的视图-视图-模型交互。但我不知道如何实现Canvas ViewModel交互。这意味着,当用户在对话框中请求在给定坐标下指定大小的标题矩形时,我知道如何在视图模型的树中添加该标题对象,但我不知道如何从视图模型的树更新画布。如何绘制画布以反映viewmodel中的对象树,然后在每次viewmodel更改时(由于用户与对话框的交互)重新绘制画布?

您不应该在viewmodel中存储控件的大小和坐标等图形设置

如果我是你,我会用不同的方式来处理这个问题

视图中
,使用画布上的操作让用户更改图表和标题的位置

您可以使用使其可由用户调整大小

然后,当用户点击应用时,使用方法保存画布对象

当您需要它供以后使用时,请使用方法加载它

视图模型中
有一个命令,该命令将画布作为参数,并处理
保存
操作

例子 视图:


视图模型:

public class MainWindowViewModel
{
    public MainWindowViewModel()
    {
        ApplyCommand = new DelegateCommand<Canvas>(canvas =>
            {
                string userLayout = XamlWriter.Save(canvas);

                // save userLayout for later use ...
            });
    }

    public DelegateCommand<Canvas> ApplyCommand { get; set; }
}
公共类MainWindowViewModel
{
公共主窗口视图模型()
{
ApplyCommand=newdelegateCommand(canvas=>
{
字符串userLayout=XamlWriter.Save(画布);
//保存userLayout以供以后使用。。。
});
}
公共DelegateCommand ApplyCommand{get;set;}
}

如果应用程序专门处理布局中的更改,并且布局信息是您显示的数据,那么将布局信息放入视图模型中当然是合适的。但是,简单的表示信息不属于视图模型

为此,你需要一个不同的解决方案。考虑一下这个。 如果我需要在屏幕上找到视图模型模板的位置,我该怎么做?我的视图模型无法了解可视化树!家伙。为了解决这个问题,我用附加属性标记元素,并使用自定义布局行为或控件来查询附加属性


这与jQuery允许javascript程序员从网页获取DOM元素的方式非常相似。

一个选项是将viewmodels添加到集合,然后将其绑定到ItemsControl。如果在XAML中提供了适当的数据模板,则视图将自动绑定到数据。我拥有的Itemscontrol如下所示:

    <ItemsControl x:Name="WorksetPresenter"
                  ItemsSource="{Binding ElementName=RootWindow, Path=TableauItems}"
                  >
        <ItemsControl.Resources>
            <DataTemplate DataType="{x:Type viewModels:AnalysisViewModel}">
                 <wg:AnalysisView DataContext="{Binding DescriptiveAnalysis}"/>
            </DataTemplate>

        <!-- more datatemplates for more view/viewmodel pairs --> 

        </ItemsControl.Resources>

        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Canvas />
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
    </ItemsControl>  


TableauItems是一个可观察的集合。一旦将ViewModel添加到集合中,它就会根据datatemplate中指定的视图在画布上呈现。对于定位,您可以使用Canvas.Left和Canvas.Top属性(注意对齐!)或rendertransform。

在上面的示例中,要在Canvas中绘制的形状的几何图形在哪里?假设您要渲染圆、椭圆或矩形中的数据。。。。。。在何处指定此形状几何图形?谢谢你的看法。如果您想要一个椭圆,那么可以,但是如果视图更复杂,我通常将其作为一个单独的UserControl,然后将datacontext绑定到viewmodel,如代码片段中所示。
    <ItemsControl x:Name="WorksetPresenter"
                  ItemsSource="{Binding ElementName=RootWindow, Path=TableauItems}"
                  >
        <ItemsControl.Resources>
            <DataTemplate DataType="{x:Type viewModels:AnalysisViewModel}">
                 <wg:AnalysisView DataContext="{Binding DescriptiveAnalysis}"/>
            </DataTemplate>

        <!-- more datatemplates for more view/viewmodel pairs --> 

        </ItemsControl.Resources>

        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Canvas />
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
    </ItemsControl>