当从直接代码之外的其他位置执行操作时,如何更新 XAML 中的值?

问题描述 投票:0回答:1

我有点进退两难。一段时间以来,我一直在为一个名为 SimHub 的应用程序开发一个插件,该插件在很大程度上可以工作。我正在进入一个阶段,我想不断改进它并添加更多功能。

我的插件的部分功能是设置一个在应用程序内部使用的属性值。此设置是在“设置页面”内完成的,当值更改时,它会更新 .json 文件中的条目。然后读取 .json 中的该条目并将其分配给一个属性。

我想要做的改进就是这个。您还可以添加“操作”,这是键盘快捷键的设置。然后该快捷方式将执行指定的操作。我试图添加的操作是 2 个键。一个键可将值增加 0.1,另一个键可将值减少 0.1。

我已成功添加该操作,它会增加或减少设置 .json 文件中的值,并且属性会更新。但我想要实现的是,当按键用于递增或递减值时,我也希望该值显示在设置屏幕中。

下面是相关代码。有一点还请大家见谅。我已经省略了所有不相关的内容。

主要代码

public class OMSCPlugin : IPlugin, IDataPlugin, IWPFSettings, IWPFSettingsV2
{
    public OMSCPluginSettings Settings;

    public void Init(PluginManager pluginManager)
    {
        Logging.Current.Info((object)($"Starting plugin: OMSC Plugin - Version {VersionText}"));
        this.Settings = this.ReadCommonSettings<OMSCPluginSettings>("Settings", (Func<OMSCPluginSettings>)(() => new OMSCPluginSettings()));
        this.AttachDelegate<OMSCPlugin, double>("Settings.ACC.FuelSafetyBuffer", (Func<double>)(() => this.Settings.ACCFuelSafetyBuffer));

        this.AddAction("IncrementFSB", (a, b) =>
        {
            Settings.ACCFuelSafetyBuffer += 0.1;
            this.SaveCommonSettings<OMSCPluginSettings>("Settings", this.Settings);
        });
        this.AddAction("DecrementFSB", (a, b) =>
        {
            Settings.ACCFuelSafetyBuffer -= 0.1;
            this.SaveCommonSettings<OMSCPluginSettings>("Settings", this.Settings);
        });
    }
}

XAML排除了一堆不相关的东西

<UserControl x:Class="OzrickMajor.OMSCPlugin.OMSCPluginSettingsControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:local1="clr-namespace:OzrickMajor.OMSCPlugin"
             xmlns:local2="clr-namespace:OzrickMajor.OMSCPlugin.Sections"
             xmlns:mah="http://metro.mahapps.com/winfx/xaml/controls"
             xmlns:styles="clr-namespace:SimHub.Plugins.Styles;assembly=SimHub.Plugins"
             xmlns:ui="clr-namespace:SimHub.Plugins.UI;assembly=SimHub.Plugins"
             xmlns:wpfui="clr-namespace:SimHub.Plugins.OutputPlugins.Dash.WPFUI;assembly=SimHub.Plugins"
             xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit">

<mah:NumericUpDown Grid.Row="1" Grid.Column="0"  ValueChanged="ACCFuelSafetyBuffer_ValueChanged" x:Name="_accfuelsafetybuffer" Width="170"
                   Minimum="0.1" Maximum="5.0" Interval="0.1" StringFormat="0.0" HasDecimals="True" Cursor="Hand"/>
<Label Grid.Row="1" Grid.Column="1" VerticalAlignment="Center" Margin="5,0,0,0" FontWeight="Bold"
       Content="Fuel Safety Buffer (in Laps)"/>
<ui:ControlsEditor Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" FriendlyName="Increment FSB" ActionName="OMSCPlugin.IncrementFSB"/>
<ui:ControlsEditor Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" FriendlyName="Decrement FSB" ActionName="OMSCPlugin.DecrementFSB"/>

XAML 代码背后

public partial class OMSCPluginSettingsControl : UserControl, IComponentConnector
{
    public OMSCPlugin Plugin { get; }

    public PluginManager PluginManager { get; internal set; }

    public OMSCPluginSettingsControl()
    {
        this.InitializeComponent();
    }

    public OMSCPluginSettingsControl(OMSCPlugin plugin) : this()
    {
        this.Plugin = plugin;
        this._accfuelsafetybuffer.Value = this.Plugin.Settings.ACCFuelSafetyBuffer;
    }

    public void ACCFuelSafetyBuffer_ValueChanged(object sender, EventArgs e)
    {
        this.Plugin.Settings.ACCFuelSafetyBuffer = Math.Round((double)this._accfuelsafetybuffer.Value, 1);
        this.Plugin.SaveCommonSettings<OMSCPluginSettings>("Settings", this.Plugin.Settings);
    }
}

设置文件代码

public class OMSCPluginSettings
{
    public double ACCFuelSafetyBuffer { get; set; } = 1.5;
}

我尝试通过 xaml 的“Value”参数中的 {Binding Path=ACCFuelSafetyBuffer} 来实现我需要的功能,如下所示:

<mah:NumericUpDown Grid.Row="1" Grid.Column="0"  ValueChanged="ACCFuelSafetyBuffer_ValueChanged" x:Name="_accfuelsafetybuffer" Width="170"
                   Minimum="0.1" Maximum="5.0" Interval="0.1" StringFormat="0.0" HasDecimals="True" Cursor="Hand" 
                   Value="{Binding Path=ACCFuelSafetyBuffer}"/>
<Label Grid.Row="1" Grid.Column="1" VerticalAlignment="Center" Margin="5,0,0,0" FontWeight="Bold"
       Content="Fuel Safety Buffer (in Laps)"/>

当我在应用程序中进行编译和检查时,该框只是空白,并且不显示该值,即使该值存在于设置文件中并且已应用于属性,并且在按下按键时仍然会发生变化。我的假设是我的绑定实际上不会去任何地方,因此,空白框,即使我没有收到任何编译器错误或运行时错误。

任何帮助将不胜感激。

我希望在不添加太多额外代码的情况下做到这一点,因为我最近的另一个目标是从我第一次开始学习 C# 和编写插件时减少很多不必要的代码。

c# wpf data-binding wpf-controls
1个回答
0
投票

OMSCPluginSettings
类应实现
INotifyPropertyChanged
接口并引发
PropertyChanged
属性的
ACCFuelSafetyBuffer
事件以通知视图源属性已更改:

public class OMSCPluginSettings : INotifyPropertyChanged
{
    private double _accFuelSafetyBuffer = 1.5;
    public double ACCFuelSafetyBuffer
    {
        get { return _accFuelSafetyBuffer; }
        set { _accFuelSafetyBuffer = value; NotifyPropertyChanged(); }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged([CallerMemberName] string propertyName = "") =>
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
© www.soinside.com 2019 - 2024. All rights reserved.