private void OnSelectedAffixChanged()
        {
            _sliders.ForEach(s => s.ValueChanged -= SliderOnValueChanged);
            _sliders.Clear();
            _sliderGroups.Clear();

            if (SelectedAffix != null && !IsEmptySelection)
            {
                var ids       = new List <string>();
                var idToIndex = new Dictionary <string, int>();
                for (var i = 0; i < SelectedAffix.ValueCount; i++)
                {
                    var stat = SelectedAffix.FirstTierStats[i];
                    ids.Add(stat.Id);
                    idToIndex[stat.Id] = i;
                }

                var translations = _statTranslator.GetTranslations(ids);
                var groups       = new List <IReadOnlyList <int> >();
                foreach (var translation in translations)
                {
                    var translatedIndices = translation.Ids
                                            .Where(id => idToIndex.ContainsKey(id))
                                            .Select(id => idToIndex[id]).ToList();
                    groups.Add(translatedIndices);
                }

                foreach (var group in groups)
                {
                    var sliderGroup = new List <SliderViewModel>();

                    foreach (var valueIndex in group)
                    {
                        var ranges = SelectedAffix.GetRanges(valueIndex);
                        var ticks  = ranges.SelectMany(r => Enumerable.Range(r.From, r.To - r.From + 1))
                                     .OrderBy(i => i).Distinct();
                        var slider = new SliderViewModel(valueIndex, ticks);
                        sliderGroup.Add(slider);
                        _sliders.Add(slider);
                    }

                    var translation = new DynamicTranslation(_statTranslator, SelectedAffix, group);
                    _sliderGroups.Add(new SliderGroupViewModel(sliderGroup, translation));
                }
            }

            _sliders.ForEach(s => s.ValueChanged += SliderOnValueChanged);

            if (_sliders.Count > 0)
            {
                SliderOnValueChanged(_sliders[0], new SliderValueChangedEventArgs(_sliders[0].Value, _sliders[0].Value));
            }
            else
            {
                AffixText = "";
            }
        }
        protected AbstractCraftingViewModel(EquipmentData equipmentData, IEnumerable <TBase> bases)
        {
            EquipmentData = equipmentData;
            _bases        = bases.ToList();
            // setting the underlying field directly, setting other properties is initiated in Init()
            _selectedFirstLevel = FirstLevelList[0];
            Monitor.Freed      += (sender, args) => RecalculateItem();

            var qualityStat = new FormatTranslation("Quality: +{0}%");

            _qualitySlider               = new SliderViewModel(0, Enumerable.Range(0, 21));
            QualitySliderGroup           = new SliderGroupViewModel(new[] { _qualitySlider }, qualityStat);
            _qualitySlider.ValueChanged += QualitySliderOnValueChanged;
        }
        private void OnSelectedAffixChanged()
        {
            _sliders.ForEach(s => s.ValueChanged -= SliderOnValueChanged);
            _sliders.Clear();
            _sliderGroups.Clear();

            if (SelectedAffix != null && !IsEmptySelection)
            {
                for (int i = 0; i < SelectedAffix.StatNames.Count; i++)
                {
                    var sliderGroup = new List <SliderViewModel>();

                    for (var j = 0; j < SelectedAffix.ValueCountPerStat[i]; j++)
                    {
                        var ranges     = SelectedAffix.GetRanges(i, j);
                        var isFloatMod = ranges
                                         .Any(r => !r.From.AlmostEquals((int)r.From, 1e-5) || !r.To.AlmostEquals((int)r.To, 1e-5));
                        IEnumerable <double> ticks = ranges
                                                     .SelectMany(
                            r =>
                            Enumerable.Range((int)Math.Round(isFloatMod ? r.From * 100 : r.From),
                                             (int)Math.Round((r.To - r.From) * (isFloatMod ? 100 : 1) + 1)))
                                                     .Select(f => isFloatMod ? (double)f / 100 : f);

                        var slider = new SliderViewModel(i, j, ticks);
                        sliderGroup.Add(slider);
                        _sliders.Add(slider);
                    }

                    string groupFormat = StatNameToFormat(SelectedAffix.StatNames[i]);
                    var    group       = new SliderGroupViewModel(sliderGroup, groupFormat);
                    _sliderGroups.Add(group);
                }
            }

            _sliders.ForEach(s => s.ValueChanged += SliderOnValueChanged);

            if (_sliders.Count > 0)
            {
                SliderOnValueChanged(_sliders[0], new SliderValueChangedEventArgs(_sliders[0].Value, _sliders[0].Value));
            }
            else
            {
                AffixText = "";
            }
        }