Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/337.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/12.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# 在WPF应用程序中应用MVVM模式_C#_Wpf_Xaml_Mvvm - Fatal编程技术网

C# 在WPF应用程序中应用MVVM模式

C# 在WPF应用程序中应用MVVM模式,c#,wpf,xaml,mvvm,C#,Wpf,Xaml,Mvvm,我正在用画布上绘制的形状制作一个简单的WPF应用程序。视图由一个地图组成,该地图在地图上不同的静态位置上有几个正方形的复杂序列 MapView是一个包含viewbox和canvas的用户控件。正方形由一个带有简单画布和形状(代码中为椭圆)的用户控件表示: 这些视图显然都有一个由模型备份的ViewModel(通过视图的DataContext属性绑定) 我的问题是: 我的地图上的SquareView都有一个mousedown事件,每个视图都代表一个模型,我不知道如何在我的应用程序中优雅地实现它

我正在用画布上绘制的形状制作一个简单的WPF应用程序。视图由一个地图组成,该地图在地图上不同的静态位置上有几个正方形的复杂序列

MapView是一个包含viewbox和canvas的用户控件。正方形由一个带有简单画布和形状(代码中为椭圆)的用户控件表示:


这些视图显然都有一个由模型备份的ViewModel(通过视图的DataContext属性绑定)

我的问题是:

  • 我的地图上的SquareView都有一个mousedown事件,每个视图都代表一个模型,我不知道如何在我的应用程序中优雅地实现它(关于MVVM模式)。我应该在XAML中预定义SquareViews,然后生成模型,还是事先生成模型,然后根据运行时对模型所做的更改动态创建视图

  • 如何区分方形视图?基于(视图)模型参考?位置坐标?我想避免给每一个单独的方块起一个单独的名字

  • 将视图的DataContext设置为其对应的viewmodel的另一种方法(无需使用框架),而不是将其添加到视图的代码中

  • 有没有更好的方法在我的地图上定位正方形?(我知道画布在缩放、不同分辨率、dpi等方面不是很灵活,但想必viewbox应该可以改善这一点,尽管我还没有完全测试过)


PS请让我知道我的描述/问题是否含糊/抽象。

看看Ryan Cromwell的文章。基本上,您希望在画布上显示正方形的“列表”。他解释了如何做我认为你想要的事情。

你必须想出某种网格结构(WPF Datagrid可以为你做)。网格的优点是,它可以像行可以被视为x坐标,列可以被视为y坐标一样使用。。在开始实现之前,想象一下您想要在UI上显示什么。WPF只是一种将你的想象变为现实的技术。如果您的应用程序是UI驱动的,那么首先从UI收集所有可能的操作,在视图模型中为这些操作创建命令。

如果我理解您的问题

我认为您可以采用的方法是使用DataTemplates、ItemsControl和ContentPresentor

实际上,您要做的是告诉WPF“显示”视图模型。因为视图模型只是普通类,所以WPF不知道如何“渲染”它们。这就是数据模板的用武之地。这种方法的好处是,DataTemplate内容的DataContext将自动设置为视图模型。数据模板在窗口或用户控件资源中定义:

<Window.Resources>
    <DataTemplate DataType="{x:Type ViewModels:SquareViewModel}">
        <Views:SquareView />
    </DataTemplate>
</Window.Resources>

在您的解决方案中如何生成(视图)模型?我不知道如何实现这个,你能用额外的代码来澄清它吗?你通常需要至少明确地将DataContext设置为视图模型一次。在我的示例中,我会创建一个MainViewModel并设置MainWindow.DataContext=new MainViewModel()。MainViewModel有一个属性集合IEnumerable Squares{get;set;}。因为我已经将我的ItemsSource绑定到正方形,所以WPF将要渲染这些正方形。由于它们只是类,它将使用DataTemplate来确定是否应该实际呈现SquareView(自动将每个SquareView的datacontext设置为关联的SquareViewModel),并添加其他代码示例来回答。请注意,我使用的是窗口,但您可以使用MapView用户控件。如果您有一个用户控件,那么在“承载”该用户控件的视图上,您可以使用ContentPresenter绑定到MapViewModel,并使用一个DT将您的MapViewModel与您的MapView匹配(然后不需要在那里显式设置DataContext)。非常感谢您的帮助!用模型实现这一点是否也很容易?现在我的方块模型是通过linkedlist连接的(事实上有几种方块类型,它们是通过继承定义的)。一个正方形也可以有几个状态,这些状态也应该反映在视图中。地图的模型还有几个附加属性,以及两个方形模型引用(在我的视图中充当入口点),我仍然不太确定如何将其与视图模型相结合。
<Window.Resources>
    <DataTemplate DataType="{x:Type ViewModels:SquareViewModel}">
        <Views:SquareView />
    </DataTemplate>
</Window.Resources>
<ContentPresenter Content="{Binding SingleSquare}" />
<ItemsControl ItemsSource="{Binding Squares}" />
public class MainViewModel
{
    public IEnumerable<SquareViewModel> Squares { get; set; }

    public MainViewModel()
    {
        var squares = new List<SquareViewModel>();
        squares.Add(new SquareViewModel(15, 15,100,100, Brushes.CadetBlue, "Square One"));
        squares.Add(new SquareViewModel(75,125, 80, 80, Brushes.Indigo, "Square Two"));
        Squares = squares;
    }
}

public class SquareViewModel
{
    public int X { get; set; }
    public int Y { get; set; }
    public int Width { get; set; }
    public int Height { get; set; }
    public Brush Color { get; set; }
    public string Name { get; set; }

    public SquareViewModel(int x, int y, int width, int height, Brush color, string name)
    {
        X = x;
        Y = y;
        Width = width;
        Height = height;
        Color = color;
        Name = name;
    }
}
<UserControl x:Class="MapView.Views.SquareView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    >
    <Grid Background="{Binding Color, FallbackValue=Azure}">
        <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding Name, FallbackValue=None}" />     
    </Grid>
</UserControl>

<Window x:Class="MapView.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:ViewModels="clr-namespace:MapView.ViewModels" 
    xmlns:Views="clr-namespace:MapView.Views" Title="Window1" Height="300" Width="300">
    <Window.Resources>
        <DataTemplate DataType="{x:Type ViewModels:SquareViewModel}">
            <Views:SquareView />
        </DataTemplate>
    </Window.Resources>
    <ItemsControl ItemsSource="{Binding Squares}" >
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Canvas HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="Beige" />
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemContainerStyle>
            <Style TargetType="ContentPresenter">
                <Setter Property="Canvas.Left"
                    Value="{Binding X}" />
                <Setter Property="Canvas.Top"
                    Value="{Binding Y}" />
                <Setter Property="Width"
                    Value="{Binding Width}" />
                <Setter Property="Height"
                    Value="{Binding Height}" />
            </Style>
        </ItemsControl.ItemContainerStyle>
    </ItemsControl>
</Window>
public partial class Window1 : Window
{
    public Window1()
    {
        InitializeComponent();
        DataContext = new MainViewModel();
    }
}