Warm tip: This article is reproduced from serverfault.com, please click

其他-UWP和ReactiveUI –如何(有时)同步两个滑块值?

(其他 - UWP and ReactiveUI – How do I (sometimes) synchronise two sliders values?)

发布于 2020-11-27 15:04:47

在我的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()代码取消注释时(如我将在实际应用程序中看到的那样),这没有问题,但是我想知道是否有一种方法不必限制它(以防万一我在以后的项目中需要这样做) )。

Questioner
GarryP
Viewed
0
Đøharrrck 2020-12-02 23:40:21

我会将其逻辑添加到视图模型中,以便视图仅包含绑定。它应该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