在我的XAML中,我有两个滑块和一个切换按钮:
<Slider
x:Name="rightSlider"
Header="Right"
Maximum="20"
Minimum="0" />
<Slider
x:Name="suffixSlider"
Header="Suffix"
Maximum="20"
Minimum="0" />
<ToggleButton
x:Name="toggleSuffixLockButton"
Content="Lock" />
在我后面的代码中,我将它们绑定如下:
this.Bind(ViewModel,
viewModel => viewModel.RightSliderValue,
view => view.rightSlider.Value)
.DisposeWith(disposableRegistration);
this.Bind(ViewModel,
viewModel => viewModel.SuffixSliderValue,
view => view.suffixSlider.Value)
DisposeWith(disposableRegistration);
this.OneWayBind(ViewModel,
viewModel => viewModel.SuffixIsLocked,
view => view.suffixSlider.IsEnabled,
value => value == false ? true : false)
.DisposeWith(disposableRegistration);
this.Bind(ViewModel,
viewModel => viewModel.SuffixIsLocked,
view => view.toggleSuffixLockButton.IsChecked)
.DisposeWith(disposableRegistration);
我的视图模型具有以下声明:
[Reactive]
public double RightSliderValue { get; set; }
[Reactive]
public double SuffixSliderValue { get; set; }
[Reactive]
public bool SuffixIsLocked { get; set; }
如果未选中toggleSuffixLockButton,则用户应该能够独立更改两个滑块。这可行。
当未选中toggleSuffixLockButton时,我希望启用suffixSlider元素;这可行。
当toggleSuffixLockButton被选中时,我希望suffixSlider元素被禁用。这可行。
但是,一旦选中toggleSuffixLockButton,我也希望立即将suffixSlider值设置为rightSlider的值,然后每次rightSlider更改时(在选中toggleSuffixLockButton的情况下),那么suffixSlider也应该更改为相同的值,直到toggleSuffixLockButton不为检查; 这我不知道该怎么做。
我以为该怎么做有一个模糊的想法,但我开始转圈。
有人可以帮忙吗?
添加了额外的代码(在视图模型中)以显示“双重处理”的其他问题:
private readonly ObservableAsPropertyHelper<string> _theResult;
public string TheResult => _theResult.Value;
_theResult = this
.WhenAnyValue(
viewModel => viewModel.RightSliderValue,
viewModel => viewModel.SuffixSliderValue,
(right, suffix) => new GenerationParameters(right, suffix))
// .Throttle(TimeSpan.FromMilliseconds(200))
.DistinctUntilChanged()
.SelectMany(GetResult) // GetResult simply returns a string based on the right and suffix values.
.ObserveOn(RxApp.MainThreadScheduler)
.ToProperty(this, x => x.TheResult, String.Empty);
无论何时启用锁定(按照下面提供的代码),都会针对RightSliderValue更改和SuffixSliderValue更改重新计算_theResult,一次又一次(或者因为它是异步的,所以我不确定)。
当.Throttle()代码取消注释时(如我将在实际应用程序中看到的那样),这没有问题,但是我想知道是否有一种方法不必限制它(以防万一我在以后的项目中需要这样做) )。
我会将其逻辑添加到视图模型中,以便视图仅包含绑定。它应该WhenAnyValue
在视图模型构造函数resp中使用这两个语句。WhenActivated
堵塞:
// sets the suffix slider to the position of right slider
// if suffix gets locked
this.WhenAnyValue(x => x.SuffixIsLocked)
.Where(locked => locked)
.Subscribe(_ => SuffixSliderValue = RightSliderValue);
// keeps both sliders in sync if suffix is locked
this.WhenAnyValue(x => x.RightSliderValue)
.Where(_ => SuffixIsLocked)
.Subscribe(_ => SuffixSliderValue = RightSliderValue);
// second part: GetResult
// observable for right slider if not SuffixIsLocked
IObservable<GenerationParameters> parametersFromRight = this
.WhenAnyValue(
viewModel => viewModel.RightSliderValue,
(right) => new GenerationParameters(right, SuffixSliderValue))
.Where(_ => !SuffixIsLocked);
// observable for suffix slider
IObservable<GenerationParameters> parametersFromSuffix = this
.WhenAnyValue(
viewModel => viewModel.SuffixSliderValue,
(suffix) => new GenerationParameters(RightSliderValue, suffix));
// merge and create property
_theResult = parametersFromRight
.Merge(parametersFromSuffix)
.DistinctUntilChanged()
.SelectMany(GetResult)
.ObserveOn(RxApp.MainThreadScheduler)
.ToProperty(this, x => x.TheResult, string.Empty);
// catch exceptions
_theResult.ThrownExceptions.Subscribe(ex => Console.WriteLine(ex.Message));
编辑:更新了问题第二部分的代码。注意:这只会在合并后捕获异常,即在中的异常,GetResult
而不是在的构造函数中发生的异常GenerationParameters
。
这在我的应用程序中确实非常有效,因为我现在拥有它,非常感谢。我现在担心的是,当锁定处于锁定状态时,将导致单独的可观察对象重新计算两次。我已经在上面的帖子中添加了额外的代码。我有什么办法可以避免这种情况?抱歉不要一开始就添加此代码,但我仍在尝试以较小的步骤学习ReactiveUI,同时又尝试不学习不良的做事方法。
DistinctUntilChanged
之所以无法正常工作,是因为您在每次更改任何滑块值时都创建了一个新实例。您可以GenerationParameters
在类/结构本身中更改的相等行为,也可以编写一个IEqualityComparer
用作参数DistinctUntilChanged
的Equals
方法,如果两个实例的right和后缀的值相同,则该方法提供true。再次感谢您再次与我联系。我创建了一个新的IEqualityComparer类,但是该类不起作用,因为先更改了SuffixSliderValue,然后更改了RightSliderValue。因此,当它们锁定在12时,我将RightSliderValue从12更改为13,我得到的序列(右12,后缀13),(右13,后缀13)都不同,因此不相等。也许我只是用错了。我需要对此有所考虑,但是您可以提供任何进一步的帮助将非常感激,因为我完全独自一人工作,没有人问(除非在这里)问题。
是的,没想到。对我来说,如果我将
_theResult = this.WhenAnyValue
in拆分为两个语句并在第一个语句中添加“ Where(_ =>!SuffixIsLocked)”,则现在可以正常工作,以便在锁定切换按钮时忽略右侧滑块的更改。顺便说一句:你有一个SelectMany(GetResult)
声明而不是Select
吗?这甚至不应该编译,因为这将返回char的observable而不是字符串的observable。SelectMany()似乎工作正常。如果我尝试使用Select()而不是SelectMany(),则会收到CS0411错误,可以通过做正确的事来纠正此错误,但我不知道当前什么是正确的事。我将看待将_theResult = this.WhenAnyValue语句拆分为两个,但这听起来令人困惑,因为听起来我将同时给同一个变量两个不同的“值”(或一个取消另一个值),这似乎很奇怪,但我可能不明白您的意思。我需要进行实验,看看会发生什么。