[英]Applying MVVM pattern in a WPF application
我正在制作一個簡單的WPF應用程序,其中包含在畫布上繪制的形狀。 視圖由地圖組成,該地圖在地圖上的不同靜態位置上具有幾個復雜的幾個正方形序列。
MapView是一個包含視圖框和畫布的UserControl。 正方形由UserControl表示,其中包含一個簡單的畫布和一個形狀(代碼中的橢圓):
<Canvas>
<Canvas.Resources>
<BooleanToVisibilityConverter x:Key="boolToVisibility" />
</Canvas.Resources>
<Ellipse Stroke="Black" Fill="{Binding Color}" Width="{Binding Dimension}" Height="{Binding Dimension}" />
<Ellipse Stroke="Black" Fill="Black" Canvas.Top="15" Canvas.Left="15" Width="20" Height="20" Visibility="{Binding IsOccupied, Converter={StaticResource boolToVisibility}}" />
</Canvas>
這些視圖顯然都具有ViewModel(通過視圖的DataContext屬性綁定),由模型備份。
我的問題:
我的地圖上的SquareViews都有一個mousedown事件,每個視圖都代表一個模型,我對如何在我的應用程序中以優雅的方式實現它感到困惑(關於MVVM模式)。 我應該在XAML中預定義SquareViews,然后生成模型,還是事先生成模型,並根據在運行時對模型所做的更改動態創建視圖。
如何區分SquareViews? 基於(查看)模型參考? 位置坐標? 我想避免給每個單獨的廣場分別給出一個名字......
將視圖的DataContext設置為相應的viewmodel(無需使用框架)的其他方法,而不是將其添加到視圖的代碼隱藏中。
有沒有更好的方法來定位我的地圖上的方塊? (我知道畫布在縮放,不同分辨率,dpi等方面不是很靈活,但據說視圖框應該改進這一點,盡管我還沒有完全測試過)
PS如果我的描述/問題是含糊不清的,請告訴我。
如果我理解你的問題......
我認為您可以采用的方法是使用DataTemplates,ItemsControl和ContentPresentor。
實際上,您要做的是告訴WPF“顯示”您的視圖模型。 因為您的視圖模型只是普通類,所以WPF不知道如何“渲染”它們。 這就是DataTemplates的用武之地。這種方法的好處是DataTemplate內容的DataContext將自動設置為視圖模型。 DataTemplates在Window或UserControl資源中定義:
<Window.Resources>
<DataTemplate DataType="{x:Type ViewModels:SquareViewModel}">
<Views:SquareView />
</DataTemplate>
</Window.Resources>
當WPF遇到SquareViewModel時,上面的代碼將呈現SquareView用戶控件(並將SquareView上的DataContext設置為SquareViewModel)。
要將視圖模型放置在視圖中,您可以使用ContentPresenter(對於單個ViewModel):
<ContentPresenter Content="{Binding SingleSquare}" />
在您的情況下,您將希望顯示一組SquareViewModel項目,因此您將需要使用ItemsControl:
<ItemsControl ItemsSource="{Binding Squares}" />
但是這不會給你想要的結果,因為默認情況下它會像ListBox一樣。 您需要將模板應用於ItemsControl以使用底層Canvas。 有關可能的實施,請參閱Pete Brown撰寫的此博客 。
祝好運!
編輯:附加代碼示例
查看型號:
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>
並在Window1構造函數中:
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
DataContext = new MainViewModel();
}
}
看看Ryan Cromwell撰寫的這篇博客 。 基本上,您希望在畫布上顯示正方形的“列表”。 他解釋了如何做到我想你的要求。
你必須想出某種網格結構(WPF Datagrid會為你做)。 網格的優點是可以像行一樣使用它可以被視為x坐標和列作為y坐標。在開始實現之前,想象一下你想要在UI上顯示什么。 WPF只是一種將您的想象力變為現實的技術。 如果您的應用程序是UI驅動的,那么首先收集可能來自UI的所有操作,為視圖模型中的那些操作創建命令。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.