1

假设我有 3 个或更多滑块,每个滑块的值可以从 0 到 100。但是我希望所有滑块值的总和 <= 100。如果我有 4 个滑块,每个滑块的最大值将为 25。

每个滑块都有一个与双变量的绑定,每次用户使用滑块(滴答频率 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>

隐藏代码(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 回答