c# - 用于编辑 user.settings 的 WPF 窗口。为什么价值观不变?
问题描述
我正在使用 wpf 窗口来编辑用户设置。
这是我到目前为止所做的:
<ListView Grid.Row="1"
ItemsSource="{Binding Source={x:Static properties:Settings.Default}, Path=PropertyValues}"
HorizontalContentAlignment="Stretch" Background="LightGray"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListView.ItemTemplate>
<DataTemplate>
<DockPanel HorizontalAlignment="Stretch"
IsEnabled="{Binding DataContext.Enabled, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}">
<Label Width="200" Content="{Binding Name}"/>
<Label Width="200" Content="{Binding Path=Property.PropertyType}" Foreground="Gray" FontStyle="Italic"/>
<ContentControl VerticalContentAlignment="Center" Content="{Binding Path=PropertyValue}">
<ContentControl.Resources>
<ResourceDictionary>
<DataTemplate DataType="{x:Type sys:Boolean}">
<CheckBox IsChecked="{Binding Path=., Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
<DataTemplate DataType="{x:Type sys:String}">
<TextBox Text="{Binding Path=., Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
<DataTemplate DataType="{x:Type sys:Int32}">
<TextBox Text="{Binding Path=., Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
</ResourceDictionary>
</ContentControl.Resources>
</ContentControl>
</DockPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
这些值正在显示,Properties.Settings.Default
但当我更改并使用Properties.Settings.Default.Save();
. 双向绑定是否正确?
谢谢
解决方案
正如评论和这个答案中所建议的,我需要将其封装System.Configuration.SettingsPropertyValue
到实现的 ViewModel 中INotifyPropertyChanged
。否则绑定将不起作用。
视图模型:
public class SettingsPropertyValueProxy : INotifyPropertyChanged
{
public string Name { get; }
public Type PropertyType => PropertyValue.GetType();
public object PropertyValue
{
get
{
return Properties.Settings.Default[Name];
}
set
{
try
{
Properties.Settings.Default[Name] = Convert.ChangeType(value, PropertyType);
Properties.Settings.Default.Save();
}
catch
{ }
}
}
public SettingsPropertyValueProxy(string name)
{
Name = name;
Properties.Settings.Default.PropertyChanged += (sender, e) => _OnPropertyChanged(e.PropertyName);
}
private void _OnPropertyChanged(string propertyName)
{
if (propertyName == Name) PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(PropertyValue)));
}
public event PropertyChangedEventHandler PropertyChanged;
}
要绑定的新属性:
public IEnumerable<SettingsPropertyValueProxy> Values { get; }
= Properties.Settings.Default.Properties
.Cast<SettingsProperty>()
.Select(p => new SettingsPropertyValueProxy(p.Name))
.OrderBy(p => p.Name)
.ToArray();
正确的视图和正确的数据模板:
<ListView Grid.Row="1"
ItemsSource="{Binding Path=Values}"
HorizontalContentAlignment="Stretch" Background="LightGray"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListView.ItemTemplate>
<DataTemplate>
<DockPanel HorizontalAlignment="Stretch"
IsEnabled="{Binding DataContext.Enabled, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}">
<Label Width="200" Content="{Binding Path=Name}"/>
<Label Width="200" Content="{Binding Path=PropertyType}" Foreground="Gray" FontStyle="Italic"/>
<!--<TextBox Text="{Binding Path=PropertyValue, Mode=TwoWay}"/>-->
<ContentControl VerticalContentAlignment="Center" Content="{Binding Path=PropertyValue}">
<ContentControl.Resources>
<ResourceDictionary>
<DataTemplate DataType="{x:Type sys:Boolean}">
<CheckBox IsChecked="{Binding Path=PropertyValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
DataContext="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DockPanel}}, Path=DataContext}"/>
</DataTemplate>
<DataTemplate DataType="{x:Type sys:String}">
<TextBox Text="{Binding Path=PropertyValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
DataContext="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DockPanel}}, Path=DataContext}"/>
</DataTemplate>
<DataTemplate DataType="{x:Type sys:Int32}">
<TextBox Text="{Binding Path=PropertyValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
DataContext="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DockPanel}}, Path=DataContext}"/>
</DataTemplate>
</ResourceDictionary>
</ContentControl.Resources>
</ContentControl>
</DockPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
推荐阅读
- versionone - VersionOne REST 查询以获取缺陷的 ToDo 小时数
- algorithm - 如何在二维数组中执行交叉 - 遗传算法
- api - 您可以使用 Xbox API 在 Java 中保持群聊吗?
- asynchronous - Flutter:Future.then() 永远不会被调用
- amazon-web-services - AWS API Gateway 授权人谷歌登录
- python - 在 Python / Scapy 网络扫描仪中按 MAC 地址过滤/标记设备识别的打印结果
- javascript - 使用 Nuxt、谷歌标签管理器和 Vuex
- python-3.x - 为大型数据集并行化 GPflow 2.0 GP 回归
- xamarin.forms - 响应式 UI 扩展视图支持该类型有一个 on_PropertyName_Changed 方法**,它是静态的
- rust - 如何在过程宏生成的代码中创建卫生标识符?