【问题标题】:How to use templates in WPF multitab UI?如何在 WPF 多选项卡 UI 中使用模板?
【发布时间】:2017-06-17 20:38:50
【问题描述】:

我是 WPF 的新手,但我尽可能地努力学习它。请帮助我克服我现在正在努力解决的问题。我正在构建一个多选项卡 UI,其中每个选项卡都应该具有完全相同的控件布局。同时,在选项卡内还有重复的控件块(标签组)。控件的内容将由来自外部源的数据填充 - 显然我将使用数据对象的实例将它们绑定到 tabitem 的 DataContext 属性:每个选项卡项一个实例。我的问题是,我不知道如何使用模板来优化代码。我想我应该使用 2 个不同的模板,一个在选项卡内,另一个用于整个选项卡,对吗?但是如何绑定数据呢?在我将为每个选项卡和代码隐藏使用的 xaml 标记下方,您可以了解这个想法。带有数字内容的标签应该绑定到对象实例(PLC)的属性上。

XAML:

<Window x:Class="WpfPromholComplementary_1.Window2"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:loc = "clr-namespace:WpfPromholComplementary_1"
    xmlns:wfi="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration"
    xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
    xmlns:dvc="clr-namespace:System.Windows.Forms.DataVisualization.Charting;assembly=System.Windows.Forms.DataVisualization"
    Title="Window2" Height="800" Width="1000">  
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="1*" />
        <ColumnDefinition Width="1*" />
        <ColumnDefinition Width="1*" />
        <ColumnDefinition Width="1*" />
        <ColumnDefinition Width="1*" />
        <ColumnDefinition Width="1*" />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="30" />
        <RowDefinition Height="210" />
        <RowDefinition Height="30" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <Border Grid.Row="1" Grid.Column="0" BorderThickness="1" BorderBrush="Blue" Margin="2" CornerRadius="8,8,8,8">
        <Grid Background="LightCyan">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="1*" />
                <ColumnDefinition Width="1*" />
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="10" />
                <RowDefinition Height="1*" />
                <RowDefinition Height="1*" />
                <RowDefinition Height="1*" />
                <RowDefinition Height="1*" />
                <RowDefinition Height="1*" />
                <RowDefinition Height="10" />
            </Grid.RowDefinitions>
            <Label Content="Module 1" Grid.Row="1" Grid.ColumnSpan="2" Height="Auto" Width="Auto" FontSize="20" HorizontalAlignment="Center"/>
            <Label Content="123.4" Grid.Row="2" Grid.Column="1" Height="Auto" Width="Auto" FontSize="20" HorizontalAlignment="Center"/>
            <Label Content="123.4" Grid.Row="3" Grid.Column="1" Height="Auto" Width="Auto" FontSize="20" HorizontalAlignment="Center"/>
            <Label Content="123.4" Grid.Row="4" Grid.Column="1" Height="Auto" Width="Auto" FontSize="20" HorizontalAlignment="Center"/>
            <Label Content="123.4" Grid.Row="5" Grid.Column="1" Height="Auto" Width="Auto" FontSize="20" HorizontalAlignment="Center"/>
            <Label Content="Channel 1:" Grid.Row="2" Grid.Column="0" Height="Auto" Width="Auto" FontSize="16" HorizontalAlignment="Center" VerticalAlignment="Center"/>
            <Label Content="Channel 2:" Grid.Row="3" Grid.Column="0" Height="Auto" Width="Auto" FontSize="16" HorizontalAlignment="Center" VerticalAlignment="Center"/>
            <Label Content="Channel 3:" Grid.Row="4" Grid.Column="0" Height="Auto" Width="Auto" FontSize="16" HorizontalAlignment="Center" VerticalAlignment="Center"/>
            <Label Content="Channel 4:" Grid.Row="5" Grid.Column="0" Height="Auto" Width="Auto" FontSize="16" HorizontalAlignment="Center" VerticalAlignment="Center"/>
        </Grid>
    </Border>
    <Border Grid.Row="1" Grid.Column="1" BorderThickness="1" BorderBrush="Blue" >
        <Grid Background="LightCyan">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="1*" />
                <ColumnDefinition Width="1*" />
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="10" />
                <RowDefinition Height="1*" />
                <RowDefinition Height="1*" />
                <RowDefinition Height="1*" />
                <RowDefinition Height="1*" />
                <RowDefinition Height="1*" />
                <RowDefinition Height="10" />
            </Grid.RowDefinitions>
            <Label Content="Module 2" Grid.Row="1" Grid.ColumnSpan="2" Height="Auto" Width="Auto" FontSize="20" HorizontalAlignment="Center"/>
            <Label Content="123.4" Grid.Row="2" Grid.Column="1" Height="Auto" Width="Auto" FontSize="20" HorizontalAlignment="Center"/>
            <Label Content="123.4" Grid.Row="3" Grid.Column="1" Height="Auto" Width="Auto" FontSize="20" HorizontalAlignment="Center"/>
            <Label Content="123.4" Grid.Row="4" Grid.Column="1" Height="Auto" Width="Auto" FontSize="20" HorizontalAlignment="Center"/>
            <Label Content="123.4" Grid.Row="5" Grid.Column="1" Height="Auto" Width="Auto" FontSize="20" HorizontalAlignment="Center"/>
            <Label Content="Channel 1:" Grid.Row="2" Grid.Column="0" Height="Auto" Width="Auto" FontSize="16" HorizontalAlignment="Center" VerticalAlignment="Center"/>
            <Label Content="Channel 2:" Grid.Row="3" Grid.Column="0" Height="Auto" Width="Auto" FontSize="16" HorizontalAlignment="Center" VerticalAlignment="Center"/>
            <Label Content="Channel 3:" Grid.Row="4" Grid.Column="0" Height="Auto" Width="Auto" FontSize="16" HorizontalAlignment="Center" VerticalAlignment="Center"/>
            <Label Content="Channel 4:" Grid.Row="5" Grid.Column="0" Height="Auto" Width="Auto" FontSize="16" HorizontalAlignment="Center" VerticalAlignment="Center"/>
        </Grid>
    </Border>
    <Border Grid.Row="1" Grid.Column="2" BorderThickness="1" BorderBrush="Blue">
        <Grid Background="LightCyan">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="1*" />
                <ColumnDefinition Width="1*" />
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="10" />
                <RowDefinition Height="1*" />
                <RowDefinition Height="1*" />
                <RowDefinition Height="1*" />
                <RowDefinition Height="1*" />
                <RowDefinition Height="1*" />
                <RowDefinition Height="10" />
            </Grid.RowDefinitions>
            <Label Content="Module 3" Grid.Row="1" Grid.ColumnSpan="2" Height="Auto" Width="Auto" FontSize="20" HorizontalAlignment="Center"/>
            <Label Content="123.4" Grid.Row="2" Grid.Column="1" Height="Auto" Width="Auto" FontSize="20" HorizontalAlignment="Center"/>
            <Label Content="123.4" Grid.Row="3" Grid.Column="1" Height="Auto" Width="Auto" FontSize="20" HorizontalAlignment="Center"/>
            <Label Content="123.4" Grid.Row="4" Grid.Column="1" Height="Auto" Width="Auto" FontSize="20" HorizontalAlignment="Center"/>
            <Label Content="123.4" Grid.Row="5" Grid.Column="1" Height="Auto" Width="Auto" FontSize="20" HorizontalAlignment="Center"/>
            <Label Content="Channel 1:" Grid.Row="2" Grid.Column="0" Height="Auto" Width="Auto" FontSize="16" HorizontalAlignment="Center" VerticalAlignment="Center"/>
            <Label Content="Channel 2:" Grid.Row="3" Grid.Column="0" Height="Auto" Width="Auto" FontSize="16" HorizontalAlignment="Center" VerticalAlignment="Center"/>
            <Label Content="Channel 3:" Grid.Row="4" Grid.Column="0" Height="Auto" Width="Auto" FontSize="16" HorizontalAlignment="Center" VerticalAlignment="Center"/>
            <Label Content="Channel 4:" Grid.Row="5" Grid.Column="0" Height="Auto" Width="Auto" FontSize="16" HorizontalAlignment="Center" VerticalAlignment="Center"/>
        </Grid>
    </Border>
    <Border Grid.Row="1" Grid.Column="3" BorderThickness="1" BorderBrush="Blue">
        <Grid Background="LightCyan">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="1*" />
                <ColumnDefinition Width="1*" />
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="10" />
                <RowDefinition Height="1*" />
                <RowDefinition Height="1*" />
                <RowDefinition Height="1*" />
                <RowDefinition Height="1*" />
                <RowDefinition Height="1*" />
                <RowDefinition Height="10" />
            </Grid.RowDefinitions>
            <Label Content="Module 4" Grid.Row="1" Grid.ColumnSpan="2" Height="Auto" Width="Auto" FontSize="20" HorizontalAlignment="Center"/>
            <Label Content="123.4" Grid.Row="2" Grid.Column="1" Height="Auto" Width="Auto" FontSize="20" HorizontalAlignment="Center"/>
            <Label Content="123.4" Grid.Row="3" Grid.Column="1" Height="Auto" Width="Auto" FontSize="20" HorizontalAlignment="Center"/>
            <Label Content="123.4" Grid.Row="4" Grid.Column="1" Height="Auto" Width="Auto" FontSize="20" HorizontalAlignment="Center"/>
            <Label Content="123.4" Grid.Row="5" Grid.Column="1" Height="Auto" Width="Auto" FontSize="20" HorizontalAlignment="Center"/>
            <Label Content="Channel 1:" Grid.Row="2" Grid.Column="0" Height="Auto" Width="Auto" FontSize="16" HorizontalAlignment="Center" VerticalAlignment="Center"/>
            <Label Content="Channel 2:" Grid.Row="3" Grid.Column="0" Height="Auto" Width="Auto" FontSize="16" HorizontalAlignment="Center" VerticalAlignment="Center"/>
            <Label Content="Channel 3:" Grid.Row="4" Grid.Column="0" Height="Auto" Width="Auto" FontSize="16" HorizontalAlignment="Center" VerticalAlignment="Center"/>
            <Label Content="Channel 4:" Grid.Row="5" Grid.Column="0" Height="Auto" Width="Auto" FontSize="16" HorizontalAlignment="Center" VerticalAlignment="Center"/>
        </Grid>
    </Border>
    <Border Grid.Row="1" Grid.Column="4" BorderThickness="1" BorderBrush="Blue">
        <Grid Background="LightCyan">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="1*" />
                <ColumnDefinition Width="1*" />
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="10" />
                <RowDefinition Height="1*" />
                <RowDefinition Height="1*" />
                <RowDefinition Height="1*" />
                <RowDefinition Height="1*" />
                <RowDefinition Height="1*" />
                <RowDefinition Height="10" />
            </Grid.RowDefinitions>
            <Label Content="Module 5" Grid.Row="1" Grid.ColumnSpan="2" Height="Auto" Width="Auto" FontSize="20" HorizontalAlignment="Center"/>
            <Label Content="123.4" Grid.Row="2" Grid.Column="1" Height="Auto" Width="Auto" FontSize="20" HorizontalAlignment="Center"/>
            <Label Content="123.4" Grid.Row="3" Grid.Column="1" Height="Auto" Width="Auto" FontSize="20" HorizontalAlignment="Center"/>
            <Label Content="123.4" Grid.Row="4" Grid.Column="1" Height="Auto" Width="Auto" FontSize="20" HorizontalAlignment="Center"/>
            <Label Content="123.4" Grid.Row="5" Grid.Column="1" Height="Auto" Width="Auto" FontSize="20" HorizontalAlignment="Center"/>
            <Label Content="Channel 1:" Grid.Row="2" Grid.Column="0" Height="Auto" Width="Auto" FontSize="16" HorizontalAlignment="Center" VerticalAlignment="Center"/>
            <Label Content="Channel 2:" Grid.Row="3" Grid.Column="0" Height="Auto" Width="Auto" FontSize="16" HorizontalAlignment="Center" VerticalAlignment="Center"/>
            <Label Content="Channel 3:" Grid.Row="4" Grid.Column="0" Height="Auto" Width="Auto" FontSize="16" HorizontalAlignment="Center" VerticalAlignment="Center"/>
            <Label Content="Channel 4:" Grid.Row="5" Grid.Column="0" Height="Auto" Width="Auto" FontSize="16" HorizontalAlignment="Center" VerticalAlignment="Center"/>
        </Grid>
    </Border>
    <Border Grid.Row="1" Grid.Column="5" BorderThickness="1" BorderBrush="Blue">
        <Grid Background="LightCyan">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="1*" />
                <ColumnDefinition Width="1*" />
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="10" />
                <RowDefinition Height="1*" />
                <RowDefinition Height="1*" />
                <RowDefinition Height="1*" />
                <RowDefinition Height="1*" />
                <RowDefinition Height="1*" />
                <RowDefinition Height="10" />
            </Grid.RowDefinitions>
            <Label Content="Module 6" Grid.Row="1" Grid.ColumnSpan="2" Height="Auto" Width="Auto" FontSize="20" HorizontalAlignment="Center"/>
            <Label Content="123.4" Grid.Row="2" Grid.Column="1" Height="Auto" Width="Auto" FontSize="20" HorizontalAlignment="Center"/>
            <Label Content="123.4" Grid.Row="3" Grid.Column="1" Height="Auto" Width="Auto" FontSize="20" HorizontalAlignment="Center"/>
            <Label Content="123.4" Grid.Row="4" Grid.Column="1" Height="Auto" Width="Auto" FontSize="20" HorizontalAlignment="Center"/>
            <Label Content="123.4" Grid.Row="5" Grid.Column="1" Height="Auto" Width="Auto" FontSize="20" HorizontalAlignment="Center"/>
            <Label Content="Channel 1:" Grid.Row="2" Grid.Column="0" Height="Auto" Width="Auto" FontSize="16" HorizontalAlignment="Center" VerticalAlignment="Center"/>
            <Label Content="Channel 2:" Grid.Row="3" Grid.Column="0" Height="Auto" Width="Auto" FontSize="16" HorizontalAlignment="Center" VerticalAlignment="Center"/>
            <Label Content="Channel 3:" Grid.Row="4" Grid.Column="0" Height="Auto" Width="Auto" FontSize="16" HorizontalAlignment="Center" VerticalAlignment="Center"/>
            <Label Content="Channel 4:" Grid.Row="5" Grid.Column="0" Height="Auto" Width="Auto" FontSize="16" HorizontalAlignment="Center" VerticalAlignment="Center"/>
        </Grid>
    </Border>
    <StackPanel Margin="5,5,5,5"  Grid.Row="3" Grid.ColumnSpan="4">
        <WindowsFormsHost>
            <dvc:Chart x:Name="chart" />
        </WindowsFormsHost>
    </StackPanel>
    <StackPanel Grid.Row="0" Grid.ColumnSpan="6" Orientation="Horizontal">
        <Label Content="IP-address:" Height="33" Width="Auto" FontSize="20" Padding="5,0,5,5"/>
        <Label Content="192.168.1.10" Height="33" Width="Auto" FontSize="20" Padding="5,0,5,5"/>
    </StackPanel>
    <DataGrid x:Name="dgDataGrid" Grid.Row="4" Grid.Column="4" Grid.ColumnSpan="2" IsSynchronizedWithCurrentItem="False"/>
</Grid>

代码隐藏:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Windows.Forms.DataVisualization.Charting;
using System.Drawing;

namespace WpfPromholComplementary_1
{
/// <summary>
/// Interaction logic for Window2.xaml
/// </summary>
public partial class Window2 : Window
{
    public Window2()
    {
        InitializeComponent();

        PLC plc1 = new PLC { ID = 1, Module_Number = "1", Channel_1 =  "1234", Channel_2 = "5678", Channel_3 = "9012", Channel_4 = "3456" };
        this.DataContext = plc1;

    }
}
}

【问题讨论】:

  • 您在谈论选项卡,但您只是在网格中使用了一些边框。为了更好地遵循这个想法(来自文本)您可以尝试查找TabControl,其中有TabItems,并允许使用模板。
  • 我刚刚又复习了一遍,编了一个小教程
  • 抱歉解释混乱。我将使用最外层网格标记内的整个布局作为选项卡的模板。只有控件的内容会有所不同...@Tatranskymedved

标签: c# wpf xaml user-interface


【解决方案1】:

我必须决定分两部分回答。一部分将采用 Code-Behind 方法,另一部分将采用 MVVM (Model-View-ViewModel)。

格式化窗口上部的最佳想法是使用相同的组件,您将在其中定义源,而不是模板。模板在您拥有一个控件并且想要更改其外观(控件布局)的地方很有用。

首先你应该创建自己的UserControl(我在例子中称之为MyModuleFrame):

XML:

<UserControl x:Class="WpfPromholComplementary_1.MyModuleFrame"
         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:WpfPromholComplementary_1"
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300"
         x:Name="mUserControl">
<Border BorderThickness="1" BorderBrush="Blue" CornerRadius="8,8,8,8">
    <Grid Background="LightCyan">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="10" />
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />
            <RowDefinition Height="10" />
        </Grid.RowDefinitions>

        <Label Content="{Binding ItemSource.Number, ElementName=mUserControl}" Grid.Row="1" Grid.ColumnSpan="2" FontSize="20" HorizontalAlignment="Center"/>
        <Label Content="{Binding ItemSource.Ch1, ElementName=mUserControl}" Grid.Row="2" Grid.Column="1" FontSize="20" HorizontalAlignment="Center" VerticalAlignment="Center"/>
        <Label Content="{Binding ItemSource.Ch2, ElementName=mUserControl}" Grid.Row="3" Grid.Column="1" FontSize="20" HorizontalAlignment="Center" VerticalAlignment="Center"/>
        <Label Content="{Binding ItemSource.Ch3, ElementName=mUserControl}" Grid.Row="4" Grid.Column="1" FontSize="20" HorizontalAlignment="Center" VerticalAlignment="Center"/>
        <Label Content="{Binding ItemSource.Ch4, ElementName=mUserControl}" Grid.Row="5" Grid.Column="1" FontSize="20" HorizontalAlignment="Center" VerticalAlignment="Center"/>
        <Label Content="Channel 1:" Grid.Row="2" FontSize="16" HorizontalAlignment="Center" VerticalAlignment="Center"/>
        <Label Content="Channel 2:" Grid.Row="3" FontSize="16" HorizontalAlignment="Center" VerticalAlignment="Center"/>
        <Label Content="Channel 3:" Grid.Row="4" FontSize="16" HorizontalAlignment="Center" VerticalAlignment="Center"/>
        <Label Content="Channel 4:" Grid.Row="5" FontSize="16" HorizontalAlignment="Center" VerticalAlignment="Center"/>

    </Grid>
</Border>
</UserControl>

C#:

namespace WpfPromholComplementary_1
{
/// <summary>
/// Interaction logic for MyModuleFrame.xaml
/// </summary>
public partial class MyModuleFrame : UserControl
{
    public MyModuleFrame()
    {
        InitializeComponent();
    }

    public Module ItemSource
    {
        get { return (Module)GetValue(ItemSourceProperty); }
        set { SetValue(ItemSourceProperty, value); }
    }
    // Using a DependencyProperty as the backing store for ItemsSource.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ItemSourceProperty =
        DependencyProperty.Register("ItemSource", typeof(Module), typeof(MyModuleFrame), new PropertyMetadata(default(Module)));
    }
}

定义设置所有UserControls的属性为DependencyProperty是非常重要的。 为什么? 因为 WPF 使用它们来完成与视图处理相关的所有工作。在初始化时,它们在 WPF 框架中注册,一旦有人想要访问它们/它们将调用 WPF(返回值),而不是直接方法。

一旦你定义了控件,你就可以在窗口上使用它。我从开始删除了一些代码(我没有参考)和结束代码,所以你有一个想法:

<Window x:Class="WpfPromholComplementary_1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:loc = "clr-namespace:WpfPromholComplementary_1"
xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
Title="Window2" Height="800" Width="1000">
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="1*" />
        <ColumnDefinition Width="1*" />
        <ColumnDefinition Width="1*" />
        <ColumnDefinition Width="1*" />
        <ColumnDefinition Width="1*" />
        <ColumnDefinition Width="1*" />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="30" />
        <RowDefinition Height="210" />
        <RowDefinition Height="30" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <loc:MyModuleFrame Grid.Row="1" Grid.Column="0" ItemSource="{Binding Module1}"/>
    <loc:MyModuleFrame Grid.Row="1" Grid.Column="1" ItemSource="{Binding Module2}"/>
    <loc:MyModuleFrame Grid.Row="1" Grid.Column="2" ItemSource="{Binding Module3}"/>
    <loc:MyModuleFrame Grid.Row="1" Grid.Column="3" ItemSource="{Binding Module4}"/>
    <!-- other modules & stuff-->
  </Grid>
</Window>

一旦达到上述目的,您需要获取动态数据,可以通过 3 种方式获得:

  • 通过从代码隐藏插入(Win-forms 方法,例如:TextBox1.ModuleNumber="3" - 不太抽象且不用于大型应用程序)
  • 通过绑定到Code-Behind(在Code-Behind中定义属性,设置Window的dataContext为this
  • 通过绑定到视图模型(遵循 MVVM 模式)-some tutorial here

根据选择的选项,您必须更新上面的代码。

我们还应该为我们的 App - Module 类定义模型。下面的这段代码不支持视图更新。如需支持,您必须实现 INotifyPropertyChanged 接口(更多内容见下文):

//Simplified
public class Module
{
    public string Number { get; set; }
    public double Ch1 { get; set; }
    public double Ch2 { get; set; }
    public double Ch3 { get; set; }
    public double Ch4 { get; set; }
}

视图模型:

public class MainViewModel
{
    public Module Module1 { get; set; } = new Module()
    {
        Number = "1",
        Ch1 = 123.4,
        Ch2 = 123.4,
        Ch3 = 123.4,
        Ch4 = 123.4
    };

    /* other modules... */
}

MVVM 方法:

App.config:

<Application x:Class="WpfPromholComplementary_1.App"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:local="clr-namespace:WpfPromholComplementary_1"
         StartupUri="MainWindow.xaml">
<Application.Resources>
    <local:MainViewModel x:Key="MainViewModel"/>
</Application.Resources>
</Application>

代码隐藏方法:

View.cs:

public partial class Window
{

    public Window()
    {
        InitializeComponent();
        this.DataContext = this;
    }

    public Module Module1 { get; set; } = new Module(); //in this case You do not need ViewModel
}

此时您应该有工作应用程序,您无法更改任何内容。

现在有两种方法可以更新 View 中的值,一种是遵循 MVVM 的正确方式,另一种是再次在代码隐藏中。 我将两者都描述仅供参考:

首先,您的 Modul 需要从 INotifyPropertyChange 继承(仅针对 2 个属性的示例):

using System.ComponentModel;
public class Module : INotifyPropertyChanged
{
    private string _number;
    public string Number
    {
        get { return this._number; }
        set
        {
            if (_number == value) return;
            _number = value;
            OnPropertyChanged(nameof(Number));
        }
    }

    private double _ch1;
    public double Ch1
    {
        get { return this._ch1; }
        set
        {
            if (_ch1 == value) return;
            _ch1 = value;
            OnPropertyChanged(nameof(Ch1));
        }
    }


    //other channels fits there

    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string aNameOfProperty)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(aNameOfProperty));
    }
}

代码隐藏:

现在假设我们要处理按钮点击事件 (XML):

<Button Click="MyButton_Click"/>

在代码隐藏中,我们可以做(C#):

private void MyButton_Click(object sender, MouseEventArgs e)
{
    //Your ViewModel is stored in DataContext, You can just cast to approach properties
    var VM = (this.DataContext as MainViewModel);
    VM.Module1.Number = "Module Number Xyz";
}

MVVM: MVVM 方法有点困难,因为您需要在某些命令类see relay command for reference 上实现 ICommand 接口。

一旦你有了这个,XML:

<Button Command="{Binding DoSomeWorkCmd}"/>

在您的 ViewModel 中:

private ICommand _DoSomeWorkCmd;
public ICommand DoSomeWorkCmd
{
    get
    {
        if (_DoSomeWorkCmd != null) return _DoSomeWorkCmd;

            _DoSomeWorkCmd = new RelayCommand((object aParam)=> { return true; }, (object aParam) =>
            {
                this.Module1.Number = "MyNewNumber XyZ";
            });

            return this._DoSomeWorkCmd;
    }
}

整个解决方案的 MVVM 示例可以在我的 GIT 上下载: https://github.com/Tatranskymedved/WpfPromholComplementary_1

【讨论】:

  • 太棒了!有用!太感谢了!惊讶于您如此迅速地找到解决方案并进行了全面的解释! @Tatranskymedved
  • 您好!再次需要你的帮助。我坚持按照您的方法实施 mvvm 。此代码行
  • 我希望我没有让你感到困惑,它现在应该可以工作了。
  • 感谢您的及时回复!只是几个问题:):
  • 很抱歉以同样的主题打扰您,- ElementName=mUserControl 中的 mUserControl 是什么?以及如何从代码隐藏中处理特定属性以更改其值?
猜你喜欢
  • 2021-03-23
  • 1970-01-01
  • 1970-01-01
  • 2012-02-20
  • 1970-01-01
  • 2011-10-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多