1

3 つ以上のスライダーがあり、各スライダーが 0 から 100 の値を持つことができるとしましょう。ただし、すべてのスライダー値の合計は <= 100 である必要があります。4 つのスライダーがある場合、全員の最大値は 25 になります。

すべてのスライダーには double 変数へのバインドがあり、ユーザーがスライダー (ティック頻度 0.1) を使用するたびに、合計を計算して他のスライダーを元に戻すか、必要に応じて同じスライダーを元に戻して、合計が <= 100 になるようにします。

問題は、計算にかなりの時間が必要であり、その間にユーザーが不正な値を設定できることです。計算が終わるまでUIをブロックすることでこれを解決したいと思います。基本的に、望ましい応答性の反対です。

スライダーの問題を解決するための他のアイデアや提案は大歓迎です。

例えば3スライダー。

スライダーバインディング

public BindingList<WLCToolParameter> WLCParameter
   {
       get { return _toolParameter; }
       set { _toolParameter = value; }
   }

インスタントであるべきです - そうではありません:(

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MCDA.Entity;
using MCDA.Extensions;

namespace MCDA.Model
{
    class ProportionalDistributionStrategy : IWeightDistributionStrategy
    {
        public void Distribute<T>(IList<T> listOfToolParameter) where T : class, IToolParameter
        {

            if (listOfToolParameter.Count == 0)
                return;

            IToolParameter lastWeightChangedToolParameter =  lastWeightChangedToolParameter = listOfToolParameter[0].LastWeightChangedToolParameter;

            double sumOfAllWeights = listOfToolParameter.Sum(t =>t.Weight);

            //we have to rescale
            if (sumOfAllWeights > 100)
            {
                double overrun = sumOfAllWeights - 100;

                //how much do we have without the locked and the last changed?
                double availableSpace = listOfToolParameter.Where(t => t.IsLocked == false && t != lastWeightChangedToolParameter).Sum(t => t.Weight);

                //we have enough by taking from the non locked
                if (availableSpace > overrun)
                {
                    //lets remove proportional
                    double sumOfChangeableWeights = listOfToolParameter.Where(t => t.IsLocked == false && t != lastWeightChangedToolParameter).Sum(t => t.Weight);

                    //in case we have only one element that is suitable we can directly remove all from this one
                    if (listOfToolParameter.Where(t => t.IsLocked == false && t.Weight > 0 && t != lastWeightChangedToolParameter).Count() == 1)
                    {
                        listOfToolParameter.Where(t => t.IsLocked == false && t.Weight > 0 && t != lastWeightChangedToolParameter).ForEach(t => t.Weight = t.Weight - overrun);
                        return;
                    }
                    listOfToolParameter.Where(t => t.IsLocked == false && t.Weight > 0 && t != lastWeightChangedToolParameter).ForEach(t => t.Weight = t.Weight - (sumOfChangeableWeights / (sumOfChangeableWeights - t.Weight)) * overrun);
                }

                //we have to resize also the latest change, but we try to keep as much as possible of the latest change
                else
                {
                    //lets set them to zero
                    listOfToolParameter.Where(t => t.IsLocked == false && t != lastWeightChangedToolParameter).ForEach(t => t.Weight = 0);

                    //how much are we still over?
                    double stillOver = listOfToolParameter.Sum(t => t.Weight) - 100;

                    //and cut from the last changed
                    listOfToolParameter.Where(t => t == lastWeightChangedToolParameter).ForEach(t => t.Weight -= stillOver);
                }
            }
        }
    }
}
4

1 に答える 1

1

データバインディングを利用していないようです。以下は簡単な例です。計算ロジックを計算メソッドに追加するだけです。UI は自動的に更新されます。これは大雑把な例であることに注意してください。このように実装するかどうかはわかりません。また、数値に小数を使用することにも注意してください。これを外国語/地域設定で使用し、小数点としてコンマを使用すると、エラーが発生します。

<Window x:Class="WpfApplication3.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <StackPanel>
            <Slider Margin="10" Value="{Binding Path=Value1}" />
            <TextBlock Text="{Binding Path=Value1}" />
            <Slider Margin="10" Value="{Binding Path=Value2}" />
            <TextBlock Text="{Binding Path=Value2}" />
            <Slider Margin="10" Value="{Binding Path=Value3}" />
            <TextBlock Text="{Binding Path=Value3}" />
        </StackPanel>

    </Grid>
</Window>

コード ビハインド (これは View Model にある MVVM アプローチ)

namespace WpfApplication3
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = this;
        }

        private double _value1;
        public double Value1
        {
            get { return _value1; }
            set
            {
                if(value != _value1)
                {
                    _value1 = value;
                    DoMyCalculations(_value1, _value2, _value3);
                    NotifyPropertChanged("Value1");
                }
            }
        }
        private double _value2;
        public double Value2
        {
            get { return _value2; }
            set
            {
                if (value != _value2)
                {
                    _value2 = value;
                    DoMyCalculations(_value1, _value2, _value3);
                    NotifyPropertChanged("Value2");
                }
            }
        }
        private double _value3;
        public double Value3
        {
            get { return _value3; }
            set
            {
                if (value != _value3)
                {
                    _value3 = value;
                    DoMyCalculations(_value1, _value2, _value3);
                    NotifyPropertChanged("Value3");
                }
            }
        }
        private bool isCalculating = false;
        private void DoMyCalculations(double value1, double value2, double value3)
        {
            if (isCalculating)
                return;
            isCalculating = true;

            // Perform logic to reset here


            isCalculating = false;
        }

        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// Notify of Property Changed event
        /// </summary>
        /// <param name="propertyName"></param>
        public void NotifyPropertChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}
于 2012-10-02T02:19:18.500 に答える