You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SimHub插件:非后置代码操作时更新XAML值的问题

解决SimHub插件设置页控件与属性同步问题

问题背景

开发SimHub插件时,已实现快捷键增减ACCFuelSafetyBuffer值的功能(可成功修改配置文件及对应属性),但设置页的NumericUpDown控件无法同步显示更新后的值。尝试添加{Binding Path=ACCFuelSafetyBuffer}绑定后,控件显示空白,无编译/运行错误,需在尽量少改动代码的前提下解决同步问题。

相关代码

主插件代码

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:mah="http://metro.mahapps.com/winfx/xaml/controls"
             xmlns:ui="clr-namespace:SimHub.Plugins.UI;assembly=SimHub.Plugins">

<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"/>
</UserControl>

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;
}

尝试的绑定修改(无效)

<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}"/>

解决方案

问题根源是缺少属性变更通知机制+绑定数据源未正确设置,只需3处小修改:

1. 让设置类实现INotifyPropertyChanged

这是WPF实现数据双向同步的核心,属性变更时通知控件更新:

using System.ComponentModel;
using System.Runtime.CompilerServices;

public class OMSCPluginSettings : INotifyPropertyChanged
{
    private double _accFuelSafetyBuffer = 1.5;
    public double ACCFuelSafetyBuffer
    {
        get => _accFuelSafetyBuffer;
        set
        {
            // 避免重复触发通知
            if (Math.Abs(_accFuelSafetyBuffer - value) < 0.001) return;
            _accFuelSafetyBuffer = value;
            OnPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

2. 设置控件绑定的数据源

在设置页构造函数中,将DataContext指向插件的Settings对象,让绑定能找到目标属性:

public OMSCPluginSettingsControl(OMSCPlugin plugin) : this()
{
    this.Plugin = plugin;
    // 绑定数据源指向Settings
    this.DataContext = plugin.Settings;
    // 移除手动赋值,绑定会自动处理初始值
    // this._accfuelsafetybuffer.Value = this.Plugin.Settings.ACCFuelSafetyBuffer;
}

3. 完善绑定配置(添加双向绑定)

修改XAML中的NumericUpDown绑定,明确设置双向绑定模式(确保控件修改和属性变更双向同步):

<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, Mode=TwoWay}"/>

验证效果

修改完成后:

  • 快捷键增减ACCFuelSafetyBuffer时,属性变更会触发PropertyChanged事件,控件自动同步显示新值
  • 设置页修改控件值时,绑定会同步更新属性,同时保留原有的保存逻辑
  • 绑定不再显示空白,初始值会自动加载

内容的提问来源于stack exchange,提问作者ashley.gibbs

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 08:09:51