ConfigNX - WPF 配置文件修改应用程序

项目概述

ConfigNX 是一个使用 WPF 开发的配置文件修改应用程序,利用 CommunityToolkit.Mvvm 8.1.0 和 Prism.DryIoc 8.1.97 库实现数据绑定、命令、视图模型和区域导航等功能。该应用程序用于管理测针、测头和机床的配置信息,提供添加、修改和删除操作。

程序架构

  • 项目名称: ConfigNX
  • 视图: MainView(主窗口)、Probe(测针)、Machine(机床)、ShowMach(显示机床详细信息)
  • 视图模型: MainViewModel、ProbeViewModel、MachineViewModel、ShowMachViewModel
  • 配置文件:
<OmvMachine>
	<ProbeLibrary>
		<Probe Name='RB-2.0-50-C' Diameter='2' Height='50'>\Configure\Model\RB-2.0-50-C.prt</Probe>
		<Probe Name='RB-3.0-30-c' Diameter='3' Height='30'>\Configure\Model\RB-3.0-30-c.prt</Probe>
		<Probe Name='RB-5.0-50-C' Diameter='6' Height='50'>\Configure\Model\RB-5.0-50-C.prt</Probe>
		<Probe Name='RB-6.0-50-c' Diameter='6' Height='50'>\Configure\Model\RB-6.0-50-c.prt</Probe>
		<Probe Name='RB-6.0-100-CF' Diameter='6' Height='100'>\Configure\Model\RB-6.0-100-CF.prt</Probe>
	</ProbeLibrary>
	<HeadLibrary>
		<Head Name='REN-OMP40' Diameter='40' Height='50'>\Configure\Model\REN-OMP40.prt</Head>
		<Head Name='REN-OMP60' Diameter='63' Height='76'>\Configure\Model\REN-OMP60.prt</Head>
		<Head Name='heidenhain_01' Diameter='40' Height='50'>\Configure\Model\heidenhain_01.prt</Head>
	</HeadLibrary>
	<Machine Sel='T' Name='CNC-1' ID='101' Probe='RB-6.0-100-CF' Head='heidenhain_01'>
		<Probe>RB-2.0-50-C</Probe>
		<Probe>RB-5.0-50-C</Probe>
		<Probe>RB-6.0-100-CF</Probe>
		<Head>REN-OMP40</Head>
		<Head>REN-heidenhain_01</Head>
	</Machine>
	<Machine Sel='F' Name='CNC-2' ID='102' Probe='RB-3.0-30-c' Head='REN-OMP60'>
		<Probe>RB-3.0-30-c</Probe>
		<Probe>RB-5.0-50-C</Probe>
		<Probe>RB-6.0-50-c</Probe>
		<Head>REN-OMP40</Head>
		<Head>REN-OMP60</Head>
	</Machine>
	<Machine Sel='F' Name='CNC-6' ID='103' Probe='RB_4.0_50_CF' Head='REN-OMP40'>
		<Probe>RB-3.0-30-c</Probe>
		<Probe>RB-6.0-50-c</Probe>
		<Probe>RB-6.0-100-CF</Probe>
		<Head>REN-OMP40</Head>
		<Head>REN-OMP60</Head>
	</Machine>
</OmvMachine>

主要功能:

  • 主窗口 (MainView)
    • 包含一个 TabControl,有两个 TabItem:Probe 和 Machine。
    • Probe TabItem: 使用 DataGrid 显示配置文件中的 ProbeLibrary 和 HeadLibrary。
    • Machine TabItem: 使用 DataGrid 显示配置文件中的所有 Machine 项,每个 Machine 项包含 Probe 和 Head 选项,使用 ComboBox 表示。
  • 显示机床详细信息窗口 (ShowMach)
    • 通过 MainView 中 Machine DataGrid 的 ContextMenu 弹出,用于添加、修改和删除 Machine 项。

数据结构:

public class ProbeCfg
{
    public string? Name { get; set; }
    public string? Diameter { get; set; }
    public string? Height { get; set; }
    public string? ModelPath { get; set; }
}

public class OmvMachine
{
    public int MachID { get; set; } 
    public string? Name { get; set; } 
    public string? ProbeName;  //测针类型
    public string? HeadName;    //测头类型
    public string? ProbeD;  //测针直径
    public string? ProbeH;  //测针高度 
    public List<string>? ProbeOpt;  //测针选项 
    public List<string>? HeadOpt;  //测头选项         
    public List<string>? ChuckOpt;  //工作台选项 
}

public partial class MachData : ObservableObject
{
    public List<ProbeCfg> ProbeLib;//测针库        
    public List<ProbeCfg> HeadLib;//测头库        
    public List<OmvMachine> MachLib;//机床库
}

视图模型:

public partial class MainViewModel : ObservableObject
public partial class MachineViewModel : ObservableRecipient, IRecipient<ValueChangedMessage<string>>
public partial class ProbeViewModel : ObservableObject
public partial class ShowMachViewModel : ObservableObject,IDialogAware

代码示例:

MainView.xaml

<Window x:Class="ConfigNX.MainView"
        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:local="clr-namespace:ConfigNX"
        xmlns:controls="clr-namespace:Microsoft.Toolkit.Wpf.UI.Controls;assembly=Microsoft.Toolkit.Wpf.UI.Controls"
        xmlns:prism="http://prismlibrary.com/" 
        mc:Ignorable="d"
        Title="ConfigNX" Height="450" Width="800">
    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="ResourceDictionary.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>
    <Grid>
        <TabControl prism:RegionManager.RegionName="MainRegion">
            <TabItem Header="Probe">
                <controls:DataGrid ItemsSource="{Binding ProbeLib}" AutoGenerateColumns="False">
                    <DataGrid.Columns>
                        <DataGridTextColumn Header="Name" Binding="{Binding Name}"/>
                        <DataGridTextColumn Header="Diameter" Binding="{Binding Diameter}"/>
                        <DataGridTextColumn Header="Height" Binding="{Binding Height}"/>
                        <DataGridTextColumn Header="Model Path" Binding="{Binding ModelPath}"/>
                    </DataGrid.Columns>
                </controls:DataGrid>
            </TabItem>
            <TabItem Header="Machine">
                <controls:DataGrid ItemsSource="{Binding MachLib}" AutoGenerateColumns="False" 
                                   SelectionMode="Single" SelectionUnit="FullRow"
                                   prism:ViewModelLocator.AutoWireViewModel="True" 
                                   ContextMenuOpening="DataGrid_ContextMenuOpening">
                    <DataGrid.ContextMenu>
                        <ContextMenu>
                            <MenuItem Header="Add" Command="{Binding AddCommand}"/>
                            <MenuItem Header="Modify" Command="{Binding ModifyCommand}" 
                                      CommandParameter="{Binding SelectedItem, RelativeSource={RelativeSource AncestorType=DataGrid}}"/>
                            <MenuItem Header="Delete" Command="{Binding DeleteCommand}" 
                                      CommandParameter="{Binding SelectedItem, RelativeSource={RelativeSource AncestorType=DataGrid}}"/>
                        </ContextMenu>
                    </DataGrid.ContextMenu>
                    <DataGrid.Columns>
                        <DataGridTextColumn Header="MachID" Binding="{Binding MachID}"/>
                        <DataGridTextColumn Header="Name" Binding="{Binding Name}"/>
                        <DataGridTextColumn Header="ProbeName" Binding="{Binding ProbeName}"/>
                        <DataGridTextColumn Header="HeadName" Binding="{Binding HeadName}"/>
                        <DataGridTextColumn Header="ProbeD" Binding="{Binding ProbeD}"/>
                        <DataGridTextColumn Header="ProbeH" Binding="{Binding ProbeH}"/>
                        <DataGridTemplateColumn Header="ProbeOpt">
                            <DataGridTemplateColumn.CellTemplate>
                                <DataTemplate>
                                    <ComboBox ItemsSource="{Binding ProbeOpt}" SelectedItem="{Binding ProbeName}"/>
                                </DataTemplate>
                            </DataGridTemplateColumn.CellTemplate>
                        </DataGridTemplateColumn>
                        <DataGridTemplateColumn Header="HeadOpt">
                            <DataGridTemplateColumn.CellTemplate>
                                <DataTemplate>
                                    <ComboBox ItemsSource="{Binding HeadOpt}" SelectedItem="{Binding HeadName}"/>
                                </DataTemplate>
                            </DataGridTemplateColumn.CellTemplate>
                        </DataGridTemplateColumn>
                        <DataGridTemplateColumn Header="ChuckOpt">
                            <DataGridTemplateColumn.CellTemplate>
                                <DataTemplate>
                                    <ComboBox ItemsSource="{Binding ChuckOpt}"/>
                                </DataTemplate>
                            </DataGridTemplateColumn.CellTemplate>
                        </DataGridTemplateColumn>
                    </DataGrid.Columns>
                </controls:DataGrid>
            </TabItem>
        </TabControl>
    </Grid>
</Window>

MainViewModel.cs

using Microsoft.Toolkit.Mvvm.ComponentModel;
using Microsoft.Toolkit.Mvvm.Input;
using Prism.Commands;
using Prism.Regions;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;

namespace ConfigNX.ViewModels
{
    public partial class MainViewModel : ObservableObject
    {
        private readonly IRegionManager _regionManager;
        private readonly MachData _machData;

        public MainViewModel(IRegionManager regionManager, MachData machData)
        {
            _regionManager = regionManager;
            _machData = machData;
        }

        public ObservableCollection<ProbeCfg> ProbeLib => new ObservableCollection<ProbeCfg>(_machData.ProbeLib);

        public ObservableCollection<OmvMachine> MachLib => new ObservableCollection<OmvMachine>(_machData.MachLib);

        public DelegateCommand AddCommand => new DelegateCommand(AddMachine);

        public DelegateCommand<OmvMachine> ModifyCommand => new DelegateCommand<OmvMachine>(ModifyMachine);

        public DelegateCommand<OmvMachine> DeleteCommand => new DelegateCommand<OmvMachine>(DeleteMachine);

        private void AddMachine()
        {
            _regionManager.RequestNavigate("MainRegion", "ShowMach", new NavigationParameters
            {
                {"Title", "Add Machine" },
                {"Action", "Add" },
                {"MachData", _machData }
            });
        }

        private void ModifyMachine(OmvMachine machine)
        {
            _regionManager.RequestNavigate("MainRegion", "ShowMach", new NavigationParameters
            {
                {"Title", "Modify Machine" },
                {"Action", "Modify" },
                {"MachData", _machData },
                {"Machine", machine }
            });
        }

        private void DeleteMachine(OmvMachine machine)
        {
            _machData.MachLib.Remove(machine);
        }
    }
}

MachineViewModel.cs

using ConfigNX.Models;
using Microsoft.Toolkit.Mvvm.ComponentModel;
using Prism.Commands;
using Prism.Regions;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;

namespace ConfigNX.ViewModels
{
    public partial class MachineViewModel : ObservableRecipient, IRecipient<ValueChangedMessage<string>>
    {
        private readonly IRegionManager _regionManager;
        private readonly MachData _machData;

        public MachineViewModel(IRegionManager regionManager, MachData machData)
        {
            _regionManager = regionManager;
            _machData = machData;
        }

        public ObservableCollection<string> ProbeOpt => new ObservableCollection<string>(_machData.ProbeLib.Select(p => p.Name));

        public ObservableCollection<string> HeadOpt => new ObservableCollection<string>(_machData.HeadLib.Select(h => h.Name));

        public ObservableCollection<string> ChuckOpt => new ObservableCollection<string>(new List<string> { "A", "B", "C" });

        public void OnReceived(ValueChangedMessage<string> message)
        {
            if (message.Key == "ProbeName")
            {
                var machine = _machData.MachLib.FirstOrDefault(m => m.ProbeName == message.OldValue);
                if (machine != null)
                {
                    machine.ProbeName = message.NewValue;
                }
            }
            else if (message.Key == "HeadName")
            {
                var machine = _machData.MachLib.FirstOrDefault(m => m.HeadName == message.OldValue);
                if (machine != null)
                {
                    machine.HeadName = message.NewValue;
                }
            }
        }

        public void SaveMachine(OmvMachine machine)
        {
            if (_machData.MachLib.Contains(machine))
            {
                // modify machine
            }
            else
            {
                // add machine
            }
            _regionManager.RequestNavigate("MainRegion", "Machine");
        }
    }
}

ProbeViewModel.cs

using ConfigNX.Models;
using Microsoft.Toolkit.Mvvm.ComponentModel;

namespace ConfigNX.ViewModels
{
    public partial class ProbeViewModel : ObservableObject
    {
        private readonly MachData _machData;

        public ProbeViewModel(MachData machData)
        {
            _machData = machData;
        }
    }
}

ShowMach.xaml

<UserControl x:Class="ConfigNX.ShowMach"
             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:ConfigNX"
             xmlns:prism="http://prismlibrary.com/" 
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800"
             prism:ViewModelLocator.AutoWireViewModel="True">
    <UserControl.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="ResourceDictionary.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </UserControl.Resources>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Grid Grid.Column="1">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>
            <Label Content="MachID:" Grid.Column="0" Grid.Row="0" Margin="5"/>
            <TextBox Text="{Binding Machine.MachID, Mode=TwoWay}" Grid.Column="1" Grid.Row="0" Margin="5"/>
            <Label Content="Name:" Grid.Column="0" Grid.Row="1" Margin="5"/>
            <TextBox Text="{Binding Machine.Name, Mode=TwoWay}" Grid.Column="1" Grid.Row="1" Margin="5"/>
            <Label Content="Probe:" Grid.Column="0" Grid.Row="2" Margin="5"/>
            <ComboBox ItemsSource="{Binding ProbeOpt}" SelectedItem="{Binding Machine.ProbeName, Mode=TwoWay}" 
                      Grid.Column="1" Grid.Row="2" Margin="5"/>
            <Label Content="Head:" Grid.Column="0" Grid.Row="3" Margin="5"/>
            <ComboBox ItemsSource="{Binding HeadOpt}" SelectedItem="{Binding Machine.HeadName, Mode=TwoWay}" 
                      Grid.Column="1" Grid.Row="3" Margin="5"/>
            <Label Content="ProbeD:" Grid.Column="0" Grid.Row="4" Margin="5"/>
            <TextBox Text="{Binding Machine.ProbeD, Mode=TwoWay}" Grid.Column="1" Grid.Row="4" Margin="5"/>
            <Label Content="ProbeH:" Grid.Column="0" Grid.Row="5" Margin="5"/>
            <TextBox Text="{Binding Machine.ProbeH, Mode=TwoWay}" Grid.Column="1" Grid.Row="5" Margin="5"/>
            <Label Content="ProbeOpt:" Grid.Column="0" Grid.Row="6" Margin="5"/>
            <ListBox ItemsSource="{Binding Machine.ProbeOpt}" SelectedItem="{Binding ProbeOptSelectedItem}" 
                     Grid.Column="1" Grid.Row="6" Margin="5"/>
            <Button Content="Add" Command="{Binding AddProbeOptCommand}" Grid.Column="1" Grid.Row="7" Margin="5"/>
            <Button Content="Delete" Command="{Binding DeleteProbeOptCommand}" Grid.Column="1" Grid.Row="8" Margin="5"/>
            <Label Content="HeadOpt:" Grid.Column="0" Grid.Row="9" Margin="5"/>
            <ListBox ItemsSource="{Binding Machine.HeadOpt}" SelectedItem="{Binding HeadOptSelectedItem}" 
                     Grid.Column="1" Grid.Row="9" Margin="5"/>
            <Button Content="Add" Command="{Binding AddHeadOptCommand}" Grid.Column="1" Grid.Row="10" Margin="5"/>
            <Button Content="Delete" Command="{Binding DeleteHeadOptCommand}" Grid.Column="1" Grid.Row="11" Margin="5"/>
            <StackPanel Grid.Column="1" Grid.Row="18" Orientation="Horizontal" HorizontalAlignment="Right">
                <Button Content="Cancel" Command="{Binding CancelCommand}" Margin="5"/>
                <Button Content="OK" Command="{Binding SaveCommand}" Margin="5"/>
            </StackPanel>
        </Grid>
    </Grid>
</UserControl>

ShowMachViewModel.cs

using ConfigNX.Models;
using Microsoft.Toolkit.Mvvm.ComponentModel;
using Prism.Commands;
using Prism.Regions;
using System.Collections.ObjectModel;

namespace ConfigNX.ViewModels
{
    public partial class ShowMachViewModel : ObservableObject, IDialogAware
    {
        private readonly IRegionManager _regionManager;
        private readonly MachData _machData;
        private string? _title;
        private string? _action;
        private OmvMachine? _machine;

        public ShowMachViewModel(IRegionManager regionManager, MachData machData)
        {
            _regionManager = regionManager;
            _machData = machData;
            AddProbeOptCommand = new DelegateCommand(AddProbeOpt);
            DeleteProbeOptCommand = new DelegateCommand(DeleteProbeOpt);
            AddHeadOptCommand = new DelegateCommand(AddHeadOpt);
            DeleteHeadOptCommand = new DelegateCommand(DeleteHeadOpt);
            SaveCommand = new DelegateCommand(SaveMachine);
            CancelCommand = new DelegateCommand(Cancel);
        }

        public ObservableCollection<string> ProbeOpt => new ObservableCollection<string>(_machData.ProbeLib.Select(p => p.Name));

        public ObservableCollection<string> HeadOpt => new ObservableCollection<string>(_machData.HeadLib.Select(h => h.Name));

        public OmvMachine? Machine
        {
            get => _machine;
            set => SetProperty(ref _machine, value);
        }

        public string? Title
        {
            get => _title;
            set => SetProperty(ref _title, value);
        }

        public string? Action
        {
            get => _action;
            set => SetProperty(ref _action, value);
        }

        public bool CanCloseDialog => true;

        public string? ProbeOptSelectedItem
        {
            get; set;
        }

        public string? HeadOptSelectedItem
        {
            get; set;
        }

        public DelegateCommand AddProbeOptCommand { get; }
        public DelegateCommand DeleteProbeOptCommand { get; }
        public DelegateCommand AddHeadOptCommand { get; }
        public DelegateCommand DeleteHeadOptCommand { get; }
        public DelegateCommand SaveCommand { get; }
        public DelegateCommand CancelCommand { get; }

        public void OnDialogClosed() { }

        public void OnDialogOpened(NavigationParameters parameters)
        {
            Title = parameters.GetValue<string>("Title");
            Action = parameters.GetValue<string>("Action");
            MachData machData = parameters.GetValue<MachData>("MachData");
            if (Action == "Modify")
            {
                Machine = parameters.GetValue<OmvMachine>("Machine");
            }
            else
            {
                Machine = new OmvMachine();
            }
        }

        private void AddProbeOpt()
        {
            if (Machine != null)
            {
                Machine.ProbeOpt?.Add(ProbeOptSelectedItem);
            }
        }

        private void DeleteProbeOpt()
        {
            if (Machine != null)
            {
                Machine.ProbeOpt?.Remove(ProbeOptSelectedItem);
            }
        }

        private void AddHeadOpt()
        {
            if (Machine != null)
            {
                Machine.HeadOpt?.Add(HeadOptSelectedItem);
            }
        }

        private void DeleteHeadOpt()
        {
            if (Machine != null)
            {
                Machine.HeadOpt?.Remove(HeadOptSelectedItem);
            }
        }

        private void SaveMachine()
        {
            if (Machine != null && Action == "Add")
            {
                _machData.MachLib.Add(Machine);
            }
            _regionManager.RequestNavigate("MainRegion", "Machine");
        }

        private void Cancel()
        {
            _regionManager.RequestNavigate("MainRegion", "Machine");
        }
    }
}

注意:

  • 上述代码示例省略了命名空间的引用。
  • 该应用程序尚未实现配置文件的读写功能,需要根据具体需求添加相应的代码。
  • 应用程序的 UI 设计和具体功能实现可以根据实际情况进行调整。

其他:

  • 使用 CommunityToolkit.Mvvm 库可以方便地实现数据绑定、命令、事件等功能。
  • 使用 Prism.DryIoc 库可以实现依赖注入,简化应用程序的开发过程。
  • 使用 Prism.Regions 库可以实现区域导航,将应用程序的 UI 拆分为多个模块,提高代码的可维护性。

总结

ConfigNX 是一个使用 WPF 开发的简单配置文件修改应用程序,可以根据实际需求进行扩展和完善。该应用程序可以作为学习 WPF、CommunityToolkit.Mvvm、Prism.DryIoc 和 Prism.Regions 库的参考示例。

项目地址: (您需要提供一个项目地址)

欢迎讨论: (您需要提供一个讨论区链接)


原文地址: https://www.cveoy.top/t/topic/nTxg 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录