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
相关产品推荐
相关产品推荐

