代码之家  ›  专栏  ›  技术社区  ›  Kirk

具有多个重复子项的MVVM Canvas

  •  0
  • Kirk  · 技术社区  · 2 年前

    我在Winforms应用程序中创建了这个面板,并试图在WPF-mvvm应用程序中复制它。

    enter image description here

    我对mvvm还是比较陌生的,我不知道最好的方法。10个小矩形中的每一个都可以保存相同的数据,所以我假设这将是一个模型:

    按钮数据模型

    public class ButtonDataModel
    {
        public SolidColorBrush BackGroundColor { get; set; }
        public int BorderThickness { get; set; }
        public SolidColorBrush BorderColor { get; set; }
        public string Text { get; set; }
        public SolidColorBrush TextColor { get; set; }
    }
    

    然后,将有一个显示数据的用户控件: 按钮数据用户控件

    <UserControl x:Class="TestApp.Views.ButtonDataPanel"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
                 xmlns:viewmodel="clr-namespace:TestApp.ViewModel"
                 d.DataContext="{d:DesignInstance Type=viewmodel:ButtonDataViewModel}"
                 mc:Ignorable="d" 
                 d:DesignHeight="25" d:DesignWidth="80">
        <Grid>
            <Border Background="{Binding ButtonData.BackGroundColor}" BorderThickness="{Binding ButtonData.BorderThickness}" BorderBrush="{Binding ButtonData.BorderColor}">
                <Label Content="{Binding ButtonData.Text}" Foreground="{Binding ButtonData.TextColor}" HorizontalAlignment="Center"/>
            </Border>  
        </Grid>
    </UserControl>
    

    然后我有另一个用户控件,它包含所有不同的较小用户控件: LcdScreen.xaml

    <UserControl x:Class="DekSim.Views.LcdScreen"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
                 xmlns:local="clr-namespace:DekSim.Views"
                 mc:Ignorable="d" 
                 d:DesignHeight="90" d:DesignWidth="480">
        <Grid>
            <ItemsControl ItemsSource="{Binding ButtonDisplays}">
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <Canvas />
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <local:ButtonDataUserControl/>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
                <ItemsControl.ItemContainerStyle>
                    <Style TargetType="ContentPresenter">
                        <Setter Property="Canvas.Left" Value="{Binding Path=XPos}" />
                        <Setter Property="Canvas.Top" Value="{Binding Path=YPos}" />
                    </Style>
                </ItemsControl.ItemContainerStyle>
            </ItemsControl>
        </Grid>
    </UserControl>
    

    每个矩形的ViewModel: 按钮数据视图模型

    public class FabViewModel : ViewModelBase
    {
        ButtonDataModel _buttonData;
    
        #region Properties
        public ButtonDataModel ButtonData
        { get { return _buttonData; } set { SetProperty(ref _buttonData, value); } }
        public int ButtonNumber { get; set; }
        public int XPos { get; set; }
        public int YPos { get; set; }
        #endregion
    }
    

    包含单个LcdScreen控件的主窗口xaml: 主窗口.xaml

    <Window x:Class="TestApp.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:views="clr-namespace:TestApp.Views"
            d:DataContext="{d:DesignInstance Type=viewmodel:MainWindowViewModel}"
            Title="Test Application" Height="750" Width="1300" WindowStartupLocation="CenterScreen"
            MinHeight="600" MinWidth="800"
            WindowStyle="SingleBorderWindow">
        <Grid>
        ....
            <views:LcdScreen Grid.Row="2" Grid.ColumnSpan="2" />
        ....
        </Grid>
    </Window>
    

    最后,MainWindowViewModel包含对ButtonDataModels的引用: 主窗口视图模型

    public class MainWindowViewModel : ViewModelBase
    {
        ObservableCollection<ButtonDataViewModel> _buttonDisplays;
    
        public ObservableCollection<ButtonDataViewModel> ButtonDisplays
        {
            get { return _buttonDisplays; }
            set { SetProperty(ref _buttonDisplays, value); }
        }
    
        public MainWindowViewModel() 
        {
            int x = 0;
            int y = 0;
            ButtonDisplays = new ObservableCollection<ButtonDataViewModel>();
            for (int i = 0; i < 10; i++)
            {
                ButtonDisplays.Add(new ButtonViewModel() 
                    { 
                        ButtonNumber = i + 1,
                        XPos = x,
                        YPos = y,
                        ButtonData = new ButtonDataModel() 
                        {
                            Text = $"Btn{i + 1}" 
                        }
                     });
                x +=80;
                if (i == 5)
                {
                    x = 0;
                    y += 50;
                }
            }
        }
    }
    

    这个设置正确吗? 如何将模型数据绑定到视图?

    1 回复  |  直到 2 年前
        1
  •  0
  •   mm8    2 年前

    的类型 BackGroundColor TextColor 属性应该是 Brush 而不是 Color

    如果我正确理解您的设置,您还应该使用 ItemTemplate 以显示 ButtonDataPanel 对于每个 ButtonDataModel 在里面 ButtonDisplays :

    <ItemsControl ItemsSource="{Binding ButtonDisplays}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Canvas />
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <local:ButtonDataPanel />
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>