为Cancel按钮提供不同的风格
This commit is contained in:
Hakoyu 2023-11-11 21:14:36 +08:00
parent 74ac695feb
commit 8462b1aab6
15 changed files with 119 additions and 300 deletions

View File

@ -1,36 +1,42 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HKW.HKWViewModels.SimpleObservable;
/// <summary>
/// 可观察值
/// </summary>
/// <typeparam name="T"></typeparam>
[DebuggerDisplay("\\{ObservableValue, Value = {Value}\\}")]
public class ObservableValue
public class ObservableValue<T>
: INotifyPropertyChanging,
INotifyPropertyChanged,
IEquatable<ObservableValue>
IEquatable<ObservableValue<T>>
{
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private object _value = default!;
private T _value = default!;
/// <summary>
/// 当前
///
/// </summary>
public object Value
public T Value
{
get => _value;
set
{
if (_value?.Equals(value) is true)
return;
NotifyPropertyChanging();
var oldValue = _value;
if (NotifyPropertyChanging(oldValue, value))
return;
_value = value;
NotifyPropertyChanged(oldValue!, value);
NotifyPropertyChanged(oldValue, value);
}
}
@ -39,6 +45,11 @@ public class ObservableValue
/// </summary>
public bool HasValue => Value != null;
/// <summary>
/// 分组
/// </summary>
public ObservableValueGroup<T>? Group { get; internal set; }
/// <summary>
/// 唯一标识符
/// </summary>
@ -50,7 +61,7 @@ public class ObservableValue
/// <inheritdoc/>
/// <param name="value">初始值</param>
public ObservableValue(object value)
public ObservableValue(T value)
{
_value = value;
}
@ -60,10 +71,16 @@ public class ObservableValue
/// <summary>
/// 通知属性改变前
/// </summary>
/// <param name="oldValue">旧值</param>
/// <param name="newValue">新值</param>
/// <returns>取消改变</returns>
protected void NotifyPropertyChanging()
private bool NotifyPropertyChanging(T oldValue, T newValue)
{
PropertyChanging?.Invoke(this, new(nameof(Value)));
var cancel = false;
// 若全部事件取消改变 则取消改变
ValueChanging?.Invoke(oldValue, newValue, ref cancel);
return cancel;
}
/// <summary>
@ -71,11 +88,10 @@ public class ObservableValue
/// </summary>
/// <param name="oldValue">旧值</param>
/// <param name="newValue">新值</param>
protected void NotifyPropertyChanged(object oldValue, object newValue)
private void NotifyPropertyChanged(T oldValue, T newValue)
{
PropertyChanged?.Invoke(this, new(nameof(Value)));
if (oldValue is null || newValue is null)
PropertyChanged?.Invoke(this, new(nameof(HasValue)));
ValueChanged?.Invoke(oldValue, newValue);
}
#endregion
@ -83,10 +99,10 @@ public class ObservableValue
/// <summary>
/// 通知发送者
/// </summary>
public ICollection<ObservableValue> NotifySenders => _notifySenders.Values;
public IReadOnlyCollection<INotifyPropertyChanged> NotifySenders => _notifySenders;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private readonly Dictionary<Guid, ObservableValue> _notifySenders = new();
private readonly HashSet<INotifyPropertyChanged> _notifySenders = new();
/// <summary>
/// 添加通知发送者
@ -98,7 +114,7 @@ public class ObservableValue
/// ObservableValue<string> value1 = new();
/// ObservableValue<string> value2 = new();
/// value2.AddNotifySender(value1);
/// value2.NotifyReceived += (source, sender) =>
/// value2.SenderPropertyChanged += (source, sender) =>
/// {
/// source.Value = sender.Value;
/// };
@ -108,27 +124,13 @@ public class ObservableValue
/// </code></para>
/// </summary>
/// <param name="items">发送者</param>
public void AddNotifySender(params ObservableValue[] items)
public void AddNotifySender(params INotifyPropertyChanged[] items)
{
foreach (var item in items)
{
item.PropertyChanged += Notify_SenderPropertyChanged;
_notifySenders.Add(item.Guid, item);
}
}
/// <summary>
/// 添加通知发送者
/// <para>
/// 注: 此方法添加的发送者不会被记录到 <see cref="NotifySenders"/> 中
/// </para>
/// </summary>
/// <param name="notices">发送者</param>
public void AddNotifySender(params INotifyPropertyChanged[] notices)
{
foreach (var item in notices)
{
item.PropertyChanged += Notify_SenderPropertyChanged;
item.PropertyChanged -= NotifySenderPropertyChanged;
item.PropertyChanged += NotifySenderPropertyChanged;
_notifySenders.Add(item);
}
}
@ -136,27 +138,12 @@ public class ObservableValue
/// 删除通知发送者
/// </summary>
/// <param name="items">发送者</param>
public void RemoveNotifySender(params ObservableValue[] items)
public void RemoveNotifySender(params INotifyPropertyChanged[] items)
{
foreach (var item in items)
{
item.PropertyChanged -= Notify_SenderPropertyChanged;
_notifySenders.Remove(item.Guid);
}
}
/// <summary>
/// 删除通知发送者
/// <para>
/// 注: 此方法删除的发送者不会从 <see cref="NotifySenders"/> 中删除
/// </para>
/// </summary>
/// <param name="notices">发送者</param>
public void RemoveNotifySender(params INotifyPropertyChanged[] notices)
{
foreach (var item in notices)
{
item.PropertyChanged -= Notify_SenderPropertyChanged;
item.PropertyChanged -= NotifySenderPropertyChanged;
_notifySenders.Remove(item);
}
}
@ -165,24 +152,14 @@ public class ObservableValue
/// </summary>
public void ClearNotifySender()
{
foreach (var sender in _notifySenders.Values)
sender.PropertyChanged -= Notify_SenderPropertyChanged;
foreach (var sender in _notifySenders)
sender.PropertyChanged -= NotifySenderPropertyChanged;
_notifySenders.Clear();
}
private void Notify_SenderPropertyChanged(object? sender, PropertyChangedEventArgs e)
private void NotifySenderPropertyChanged(object? sender, PropertyChangedEventArgs e)
{
NotifySenderPropertyChanged(this, sender);
}
/// <summary>
/// 通知接收事件
/// </summary>
/// <param name="source">源</param>
/// <param name="sender">发送者</param>
protected void NotifySenderPropertyChanged(ObservableValue source, object? sender)
{
SenderPropertyChanged?.Invoke(source, sender);
SenderPropertyChanged?.Invoke(this, (INotifyPropertyChanged)sender!);
}
#endregion
@ -196,17 +173,17 @@ public class ObservableValue
/// <inheritdoc/>
public override bool Equals(object? obj)
{
return Equals(obj as ObservableValue);
return Equals(obj as ObservableValue<T>);
}
/// <inheritdoc/>
public override int GetHashCode()
{
return Value?.GetHashCode() ?? 0;
return Guid.GetHashCode();
}
/// <inheritdoc/>
public bool Equals(ObservableValue? other)
public bool Equals(ObservableValue<T>? other)
{
return Guid.Equals(other?.Guid) is true;
}
@ -217,7 +194,7 @@ public class ObservableValue
/// <param name="value1">左值</param>
/// <param name="value2">右值</param>
/// <returns>相等为 <see langword="true"/> 否则为 <see langword="false"/></returns>
public static bool operator ==(ObservableValue value1, ObservableValue value2)
public static bool operator ==(ObservableValue<T> value1, ObservableValue<T> value2)
{
return value1.Value?.Equals(value2.Value) is true;
}
@ -228,7 +205,7 @@ public class ObservableValue
/// <param name="value1">左值</param>
/// <param name="value2">右值</param>
/// <returns>不相等为 <see langword="true"/> 否则为 <see langword="false"/></returns>
public static bool operator !=(ObservableValue value1, ObservableValue value2)
public static bool operator !=(ObservableValue<T> value1, ObservableValue<T> value2)
{
return value1.Value?.Equals(value2.Value) is not true;
}
@ -236,6 +213,7 @@ public class ObservableValue
#endregion
#region Event
/// <summary>
/// 属性改变前事件
/// </summary>
@ -246,18 +224,47 @@ public class ObservableValue
/// </summary>
public event PropertyChangedEventHandler? PropertyChanged;
/// <summary>
/// 值改变前事件
/// </summary>
public event ValueChangingEventHandler? ValueChanging;
/// <summary>
/// 值改变后事件
/// </summary>
public event ValueChangedEventHandler? ValueChanged;
/// <summary>
/// 通知接收事件
/// </summary>
public event NotifySenderPropertyChangedHandler? SenderPropertyChanged;
#endregion
#region Delegate
/// <summary>
/// 值改变事件
/// </summary>
/// <param name="oldValue">旧值</param>
/// <param name="newValue">新值</param>
/// <param name="cancel">取消</param>
public delegate void ValueChangingEventHandler(T oldValue, T newValue, ref bool cancel);
/// <summary>
/// 值改变后事件
/// </summary>
/// <param name="oldValue">旧值</param>
/// <param name="newValue">新值</param>
public delegate void ValueChangedEventHandler(T oldValue, T newValue);
/// <summary>
/// 通知发送者属性改变接收器
/// </summary>
/// <param name="source">源</param>
/// <param name="sender">发送者</param>
public delegate void NotifySenderPropertyChangedHandler(ObservableValue source, object? sender);
public delegate void NotifySenderPropertyChangedHandler(
ObservableValue<T> source,
INotifyPropertyChanged? sender
);
#endregion
}

View File

@ -46,10 +46,10 @@ public class ObservableValueGroup<T> : IEnumerable<ObservableValue<T>?>
public void Add(params ObservableValue<T>[] items)
{
foreach (var item in items)
AddX(item);
AddToGroup(item);
}
private void AddX(ObservableValue<T> item)
private void AddToGroup(ObservableValue<T> item)
{
if (item.Group is not null)
throw new ArgumentException("item.Group must be null", nameof(item));
@ -77,10 +77,10 @@ public class ObservableValueGroup<T> : IEnumerable<ObservableValue<T>?>
public void Remove(params ObservableValue<T>[] items)
{
foreach (var item in items)
RemoveX(item);
RemoveFromGroup(item);
}
private void RemoveX(ObservableValue<T> item)
private void RemoveFromGroup(ObservableValue<T> item)
{
var result = _bindingValues.Remove(item.Guid);
if (result)

View File

@ -1,204 +0,0 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HKW.HKWViewModels.SimpleObservable;
/// <summary>
/// 可观察值
/// </summary>
/// <typeparam name="T"></typeparam>
[DebuggerDisplay("\\{ObservableValue, Value = {Value}\\}")]
public class ObservableValue<T> : ObservableValue, IEquatable<ObservableValue<T>>
{
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private T _value = default!;
/// <inheritdoc cref=" ObservableValue.Value"/>
public new T Value
{
get => _value;
set
{
if (_value?.Equals(value) is true)
return;
var oldValue = _value;
if (NotifyPropertyChanging(oldValue, value))
return;
_value = value;
NotifyPropertyChanged(oldValue, value);
}
}
/// <summary>
/// 分组
/// </summary>
public ObservableValueGroup<T>? Group { get; internal set; }
#region Ctor
/// <inheritdoc/>
public ObservableValue() { }
/// <inheritdoc/>
/// <param name="value">初始值</param>
public ObservableValue(T value)
{
_value = value;
}
#endregion
#region NotifyProperty
/// <summary>
/// 通知属性改变前
/// </summary>
/// <param name="oldValue">旧值</param>
/// <param name="newValue">新值</param>
/// <returns>取消改变</returns>
private bool NotifyPropertyChanging(T oldValue, T newValue)
{
NotifyPropertyChanging();
var cancel = false;
// 若全部事件取消改变 则取消改变
ValueChanging?.Invoke(oldValue, newValue, ref cancel);
return cancel;
}
/// <summary>
/// 通知属性改变后
/// </summary>
/// <param name="oldValue">旧值</param>
/// <param name="newValue">新值</param>
private void NotifyPropertyChanged(T oldValue, T newValue)
{
base.NotifyPropertyChanged(oldValue!, newValue!);
ValueChanged?.Invoke(oldValue, newValue);
}
#endregion
#region NotifySender
/// <summary>
/// 通知发送者
/// </summary>
public new ICollection<ObservableValue<T>> NotifySenders => _notifySenders.Values;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private readonly Dictionary<Guid, ObservableValue<T>> _notifySenders = new();
/// <inheritdoc cref=" ObservableValue.AddNotifySender(ObservableValue[])"/>
public void AddNotifySender(params ObservableValue<T>[] items)
{
foreach (var item in items)
{
item.PropertyChanged += NotifySenderPropertyChanged;
_notifySenders.Add(item.Guid, item);
}
}
/// <inheritdoc cref=" ObservableValue.RemoveNotifySender(ObservableValue[])"/>
public void RemoveNotifySender(params ObservableValue<T>[] items)
{
foreach (var item in items)
{
item.PropertyChanged -= NotifySenderPropertyChanged;
_notifySenders.Remove(item.Guid);
}
}
/// <inheritdoc cref=" ObservableValue.ClearNotifySender"/>
public new void ClearNotifySender()
{
foreach (var sender in _notifySenders.Values)
sender.PropertyChanged -= NotifySenderPropertyChanged;
_notifySenders.Clear();
}
private void NotifySenderPropertyChanged(object? sender, PropertyChangedEventArgs e)
{
NotifySenderPropertyChanged(this, sender);
}
#endregion
#region Other
/// <inheritdoc/>
public override string ToString()
{
return Value?.ToString() ?? string.Empty;
}
/// <inheritdoc/>
public override bool Equals(object? obj)
{
return Equals(obj as ObservableValue<T>);
}
/// <inheritdoc/>
public override int GetHashCode()
{
return Value?.GetHashCode() ?? 0;
}
/// <inheritdoc/>
public bool Equals(ObservableValue<T>? other)
{
return Guid.Equals(other?.Guid) is true;
}
/// <summary>
/// 判断 <see cref="Value"/> 相等
/// </summary>
/// <param name="value1">左值</param>
/// <param name="value2">右值</param>
/// <returns>相等为 <see langword="true"/> 否则为 <see langword="false"/></returns>
public static bool operator ==(ObservableValue<T> value1, ObservableValue<T> value2)
{
return value1.Value?.Equals(value2.Value) is true;
}
/// <summary>
/// 判断 <see cref="Value"/> 不相等
/// </summary>
/// <param name="value1">左值</param>
/// <param name="value2">右值</param>
/// <returns>不相等为 <see langword="true"/> 否则为 <see langword="false"/></returns>
public static bool operator !=(ObservableValue<T> value1, ObservableValue<T> value2)
{
return value1.Value?.Equals(value2.Value) is not true;
}
#endregion
#region Event
/// <summary>
/// 值改变前事件
/// </summary>
public event ValueChangingEventHandler? ValueChanging;
/// <summary>
/// 值改变后事件
/// </summary>
public event ValueChangedEventHandler? ValueChanged;
#endregion
#region Delegate
/// <summary>
/// 值改变事件
/// </summary>
/// <param name="oldValue">旧值</param>
/// <param name="newValue">新值</param>
/// <param name="cancel">取消</param>
public delegate void ValueChangingEventHandler(T oldValue, T newValue, ref bool cancel);
/// <summary>
/// 值改变后事件
/// </summary>
/// <param name="oldValue">旧值</param>
/// <param name="newValue">新值</param>
public delegate void ValueChangedEventHandler(T oldValue, T newValue);
#endregion
}

View File

@ -13,6 +13,13 @@
<Setter Property="Margin" Value="10" />
<Setter Property="pu:ButtonHelper.CornerRadius" Value="24" />
</Style>
<Style
x:Key="Button_Cancel"
BasedOn="{StaticResource ThemedButtonStyle}"
TargetType="Button">
<Setter Property="Background" Value="{StaticResource PrimaryLight}" />
<Setter Property="Foreground" Value="{StaticResource SecondaryText}" />
</Style>
<Style
x:Key="Button_HiddenOnTagNull"
BasedOn="{StaticResource ThemedButtonStyle}"

View File

@ -127,7 +127,6 @@
<Compile Include="SimpleObservable\ObservableCommandT.cs" />
<Compile Include="ModMakerStyles.cs" />
<Compile Include="SimpleObservable\ObservableValueGroup.cs" />
<Compile Include="SimpleObservable\ObservableValueT.cs" />
<Compile Include="ViewModels\ModEdit\AddCultureWindowVM.cs" />
<Compile Include="ViewModels\ModEdit\AnimeEdit\FoodAnimeEditWindowVM.cs" />
<Compile Include="ViewModels\ModEdit\AnimeEdit\AnimeEditWindowVM.cs" />

View File

@ -65,7 +65,7 @@
Click="Button_Cancel_Click"
Content="{ll:Str 取消}"
IsCancel="True"
Style="{DynamicResource ThemedButtonStyle}" />
Style="{DynamicResource Button_Cancel}" />
<Button
x:Name="Button_Yes"
Grid.Column="1"

View File

@ -287,19 +287,22 @@
x:Name="Button_AddAnime"
Margin="10"
Command="{Binding AddAnimeCommand}"
Content="{ll:Str 添加动画}" />
Content="{ll:Str 添加动画}"
Style="{DynamicResource ThemedButtonStyle}" />
<Button
x:Name="Button_Cancel"
Grid.Column="1"
Margin="10"
Click="Button_Cancel_Click"
Content="{ll:Str 取消}" />
Content="{ll:Str 取消}"
Style="{DynamicResource Button_Cancel}" />
<Button
x:Name="Button_Yes"
Grid.Column="2"
Margin="10"
Click="Button_Yes_Click"
Content="{ll:Str 确定}" />
Content="{ll:Str 确定}"
Style="{DynamicResource ThemedButtonStyle}" />
</Grid>
</Grid>
</Grid>

View File

@ -627,19 +627,22 @@
x:Name="Button_AddAnime"
Margin="10"
Command="{Binding AddAnimeCommand}"
Content="{ll:Str 添加动画}" />
Content="{ll:Str 添加动画}"
Style="{DynamicResource ThemedButtonStyle}" />
<Button
x:Name="Button_Cancel"
Grid.Column="1"
Margin="10"
Click="Button_Cancel_Click"
Content="{ll:Str 取消}" />
Content="{ll:Str 取消}"
Style="{DynamicResource Button_Cancel}" />
<Button
x:Name="Button_Yes"
Grid.Column="2"
Margin="10"
Click="Button_Yes_Click"
Content="{ll:Str 确定}" />
Content="{ll:Str 确定}"
Style="{DynamicResource ThemedButtonStyle}" />
</Grid>
</Grid>
</Grid>

View File

@ -173,13 +173,15 @@
x:Name="Button_Cancel"
Margin="10"
Click="Button_Cancel_Click"
Content="{ll:Str 取消}" />
Content="{ll:Str 取消}"
Style="{DynamicResource Button_Cancel}" />
<Button
x:Name="Button_Yes"
Grid.Column="1"
Margin="10"
Click="Button_Yes_Click"
Content="{ll:Str 确定}" />
Content="{ll:Str 确定}"
Style="{DynamicResource ThemedButtonStyle}" />
</Grid>
</Grid>
<ListBox Grid.Column="2" Template="{StaticResource ListBox_ShowLangs}" />

View File

@ -191,7 +191,7 @@
Margin="10"
Click="Button_Cancel_Click"
Content="{ll:Str 取消}"
Style="{DynamicResource ThemedButtonStyle}" />
Style="{DynamicResource Button_Cancel}" />
<Button
x:Name="Button_Yes"
Grid.Column="1"

View File

@ -93,7 +93,7 @@
Margin="10"
Click="Button_Cancel_Click"
Content="{ll:Str 取消}"
Style="{DynamicResource ThemedButtonStyle}" />
Style="{DynamicResource Button_Cancel}" />
<Button
x:Name="Button_Yes"
Grid.Column="1"

View File

@ -283,7 +283,7 @@
Margin="10"
Click="Button_Cancel_Click"
Content="{ll:Str 取消}"
Style="{DynamicResource ThemedButtonStyle}" />
Style="{DynamicResource Button_Cancel}" />
<Button
x:Name="Button_Yes"
Grid.Column="1"

View File

@ -814,7 +814,7 @@
Margin="10"
Click="Button_Cancel_Click"
Content="{ll:Str 取消}"
Style="{DynamicResource ThemedButtonStyle}" />
Style="{DynamicResource Button_Cancel}" />
<Button
x:Name="Button_Yes"
Grid.Column="1"

View File

@ -163,7 +163,7 @@
Margin="10"
Click="Button_Cancel_Click"
Content="{ll:Str 取消}"
Style="{DynamicResource ThemedButtonStyle}" />
Style="{DynamicResource Button_Cancel}" />
<Button
x:Name="Button_Yes"
Grid.Column="1"

View File

@ -14,10 +14,10 @@
d:DataContext="{d:DesignInstance Type=vm:WorkEditWindowVM}"
WindowStartupLocation="CenterScreen"
mc:Ignorable="d">
<Window.Resources>
<ResourceDictionary Source="/VPet-Simulator.Windows.Interface;component/ResourceStyle.xaml" />
</Window.Resources>
<Grid>
<Window.Resources>
<ResourceDictionary Source="/VPet-Simulator.Windows.Interface;component/ResourceStyle.xaml" />
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
@ -294,13 +294,15 @@
x:Name="Button_Cancel"
Margin="10"
Click="Button_Cancel_Click"
Content="{ll:Str 取消}" />
Content="{ll:Str 取消}"
Style="{DynamicResource Button_Cancel}" />
<Button
x:Name="Button_Yes"
Grid.Column="1"
Margin="10"
Click="Button_Yes_Click"
Content="{ll:Str 确定}" />
Content="{ll:Str 确定}"
Style="{DynamicResource ThemedButtonStyle}" />
</Grid>
</Grid>
<ListBox Grid.Column="2" Template="{StaticResource ListBox_ShowLangs}" />