如何在 ViewModel 中交换 属性 值?无法通过 ref
How to swap property values in ViewModel? Can't pass by ref
我想比较和交换两个 ViewModel public 属性的值,最好使用如下方法:
void SwapIfGreater<T>(ref T lhs, ref T rhs) where T : System.IComparable<T>
{
T temp;
if (lhs.CompareTo(rhs) > 0)
{
temp = lhs;
lhs = rhs;
rhs = temp;
}
}
但是由于您不能通过 ref 传递属性,所以我无法在我的 ViewModel 中执行此操作。
private Int32 max;
public Int32 Max
{
get { return max; }
set
{
SwapIfGreater<Int32>(ref Min, ref Max);
max = value;
OnPropertyChanged("Max");
}
}
private Int32 min;
public Int32 Min
{
get { return min; }
set
{
SwapIfGreater<Int32>(ref Min, ref Max);
min = value;
OnPropertyChanged("Min");
}
}
失败...如果我只是尝试在 Min getter 或 setter 中直接使用 "if compare" 逻辑,当 Min 更改为大于 Max 的值时,我最终得到的最小值等于最大值。
编辑:根据有关支持属性的建议,我已将方法修改为:
void SwapIfGreater<T>(ref T lhs, ref T rhs, String otherPropertyName) where T : System.IComparable<T>
{
T temp;
if (lhs.CompareTo(rhs) > 0)
{
temp = lhs;
lhs = rhs;
rhs = temp;
OnPropertyChanged(otherPropertyName);
}
}
和"Min"属性setter到这个:
min = value;
SwapIfGreater<Int32>(ref min, ref max, "Max");
OnPropertyChanged("Min");
我错过了什么?这仍然只是在Min大于Max时将Max设置为Min。
编辑:虽然我很想知道我在上面做错了什么,但再次测试了 UI 实现了我想要复制的交换行为,我意识到这是一个令人讨厌的用户体验,因为用户被迫再次单击两个选择器。如果用户选择的 Min 高于 Max,反之亦然,我将恢复到将 Max 重置为 "No Maximum" 的原始实现。
您不能通过 ref 传递属性,因为属性被转换为 getter 和 setter 方法。
改为使用属性的支持字段
SwapIfGreater<Int32>(ref min, ref max);
当您将参数作为 ref 传递时,它传递的是地址。 属性 看起来像一个值,但它实际上是一对函数,每个函数都有不同的签名。所以要传递一个属性,其实需要传递两个函数指针,一个是get,一个是set。
传递给函数的内容与传递给变量的地址完全不同
即一个变量地址 v 的两个函数指针。
因此,尽量避免将属性作为 Ref 或 Out 传递。
Dotctor 已经为您提供了正确的解决方案。
SwapIfGreater<Int32>(ref min, ref max);
我想比较和交换两个 ViewModel public 属性的值,最好使用如下方法:
void SwapIfGreater<T>(ref T lhs, ref T rhs) where T : System.IComparable<T>
{
T temp;
if (lhs.CompareTo(rhs) > 0)
{
temp = lhs;
lhs = rhs;
rhs = temp;
}
}
但是由于您不能通过 ref 传递属性,所以我无法在我的 ViewModel 中执行此操作。
private Int32 max;
public Int32 Max
{
get { return max; }
set
{
SwapIfGreater<Int32>(ref Min, ref Max);
max = value;
OnPropertyChanged("Max");
}
}
private Int32 min;
public Int32 Min
{
get { return min; }
set
{
SwapIfGreater<Int32>(ref Min, ref Max);
min = value;
OnPropertyChanged("Min");
}
}
失败...如果我只是尝试在 Min getter 或 setter 中直接使用 "if compare" 逻辑,当 Min 更改为大于 Max 的值时,我最终得到的最小值等于最大值。
编辑:根据有关支持属性的建议,我已将方法修改为:
void SwapIfGreater<T>(ref T lhs, ref T rhs, String otherPropertyName) where T : System.IComparable<T>
{
T temp;
if (lhs.CompareTo(rhs) > 0)
{
temp = lhs;
lhs = rhs;
rhs = temp;
OnPropertyChanged(otherPropertyName);
}
}
和"Min"属性setter到这个:
min = value;
SwapIfGreater<Int32>(ref min, ref max, "Max");
OnPropertyChanged("Min");
我错过了什么?这仍然只是在Min大于Max时将Max设置为Min。
编辑:虽然我很想知道我在上面做错了什么,但再次测试了 UI 实现了我想要复制的交换行为,我意识到这是一个令人讨厌的用户体验,因为用户被迫再次单击两个选择器。如果用户选择的 Min 高于 Max,反之亦然,我将恢复到将 Max 重置为 "No Maximum" 的原始实现。
您不能通过 ref 传递属性,因为属性被转换为 getter 和 setter 方法。
改为使用属性的支持字段
SwapIfGreater<Int32>(ref min, ref max);
当您将参数作为 ref 传递时,它传递的是地址。 属性 看起来像一个值,但它实际上是一对函数,每个函数都有不同的签名。所以要传递一个属性,其实需要传递两个函数指针,一个是get,一个是set。
传递给函数的内容与传递给变量的地址完全不同
即一个变量地址 v 的两个函数指针。
因此,尽量避免将属性作为 Ref 或 Out 传递。
Dotctor 已经为您提供了正确的解决方案。
SwapIfGreater<Int32>(ref min, ref max);