mirror of
https://github.com/MaaAssistantArknights/MaaAssistantArknights.git
synced 2026-07-15 17:30:27 +08:00
rft: 过期关卡使用删除线表示 (#15657)
* rft: 使用`不修改关卡`替代 显式修改为`无效关卡` * fix: 过滤过期关卡 * feat: 过期关卡增加删除线 * perf: 移除不必要的警告 * perf: 简化过滤 * fix: 无法隐藏关卡, 取消手动输入关卡名后验证关卡名有效性 --------- Co-authored-by: uye <99072975+ABA2396@users.noreply.github.com>
This commit is contained in:
@@ -57,13 +57,13 @@ internal class FightTaskStageResetModeConverter : JsonConverter<Root>
|
||||
{
|
||||
if (!taskElement.TryGetProperty("StageResetMode", out _))
|
||||
{
|
||||
if (fightTask.UseOptionalStage)
|
||||
if (fightTask.HideUnavailableStage)
|
||||
{
|
||||
fightTask.StageResetMode = FightStageResetMode.Invalid;
|
||||
fightTask.StageResetMode = FightStageResetMode.Current;
|
||||
}
|
||||
else
|
||||
{
|
||||
fightTask.StageResetMode = FightStageResetMode.Current;
|
||||
fightTask.StageResetMode = FightStageResetMode.Ignore;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
// <copyright file="FightTaskStageResetModeInvalidToIgnoreConverter.cs" company="MaaAssistantArknights">
|
||||
// Part of the MaaWpfGui project, maintained by the MaaAssistantArknights team (Maa Team)
|
||||
// Copyright (C) 2021-2025 MaaAssistantArknights Contributors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License v3.0 only as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY
|
||||
// </copyright>
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace MaaWpfGui.Configuration.Converter;
|
||||
|
||||
internal class FightTaskStageResetModeInvalidToIgnoreConverter : JsonConverter<Root>
|
||||
{
|
||||
private const string TypeDiscriminatorProperty = "$type";
|
||||
private const string FightTaskTypeName = "FightTask";
|
||||
private const string StageResetModeProperty = "StageResetMode";
|
||||
private const string InvalidValue = "Invalid";
|
||||
private const string IgnoreValue = "Ignore";
|
||||
|
||||
public override Root? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
if (reader.TokenType != JsonTokenType.StartObject)
|
||||
{
|
||||
throw new JsonException("Expected StartObject token");
|
||||
}
|
||||
|
||||
using var jsonDoc = JsonDocument.ParseValue(ref reader);
|
||||
JsonNode? rootNode = JsonNode.Parse(jsonDoc.RootElement.GetRawText());
|
||||
|
||||
if (rootNode is JsonObject rootObj)
|
||||
{
|
||||
ReplaceInvalidStageResetModeInTaskQueues(rootObj);
|
||||
}
|
||||
|
||||
string modifiedJson = rootNode?.ToJsonString() ?? string.Empty;
|
||||
return JsonSerializer.Deserialize<Root>(modifiedJson, GetOptionsWithoutThisConverter(options));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 遍历 Configurations.*.TaskQueue,将 $type 为 FightTask 且 StageResetMode 为 "Invalid" 的项改为 "Ignore"
|
||||
/// </summary>
|
||||
private static void ReplaceInvalidStageResetModeInTaskQueues(JsonObject root)
|
||||
{
|
||||
if (root["Configurations"] is not JsonObject configurations)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var (_, configNode) in configurations)
|
||||
{
|
||||
if (configNode is not JsonObject config)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (config["TaskQueue"] is not JsonArray taskQueue)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (var taskNode in taskQueue)
|
||||
{
|
||||
if (taskNode is not JsonObject task)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!IsFightTask(task))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (task[StageResetModeProperty] is JsonValue modeNode &&
|
||||
modeNode.GetValue<string>() == InvalidValue)
|
||||
{
|
||||
task[StageResetModeProperty] = IgnoreValue;
|
||||
}
|
||||
|
||||
if (task["StagePlan"] is JsonArray stagePlan)
|
||||
{
|
||||
for (int i = 0; i < stagePlan.Count; i++)
|
||||
{
|
||||
if (stagePlan[i] is JsonValue stageNode &&
|
||||
stageNode.GetValue<string>() == "__INVALID__")
|
||||
{
|
||||
stagePlan[i] = "OR-8";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断任务节点是否为 FightTask(依据 $type 字段)
|
||||
/// </summary>
|
||||
private static bool IsFightTask(JsonObject task)
|
||||
{
|
||||
if (task[TypeDiscriminatorProperty] is not JsonValue typeNode)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return typeNode.GetValue<string>() == FightTaskTypeName;
|
||||
}
|
||||
|
||||
public override void Write(Utf8JsonWriter writer, Root value, JsonSerializerOptions options)
|
||||
{
|
||||
JsonSerializer.Serialize(writer, value, GetOptionsWithoutThisConverter(options));
|
||||
}
|
||||
|
||||
private static JsonSerializerOptions GetOptionsWithoutThisConverter(JsonSerializerOptions options)
|
||||
{
|
||||
var newOptions = new JsonSerializerOptions(options);
|
||||
for (int i = newOptions.Converters.Count - 1; i >= 0; i--)
|
||||
{
|
||||
if (newOptions.Converters[i] is FightTaskStageResetModeInvalidToIgnoreConverter)
|
||||
{
|
||||
newOptions.Converters.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
return newOptions;
|
||||
}
|
||||
}
|
||||
@@ -61,7 +61,7 @@ public static class ConfigFactory
|
||||
// ReSharper disable once EventNeverSubscribedTo.Global
|
||||
public static event ConfigurationUpdateEventHandler? ConfigurationUpdateEvent;
|
||||
|
||||
private static readonly JsonSerializerOptions _options = new() { WriteIndented = true, Converters = { new JsonStringEnumConverter(), new FightTaskStageResetModeConverter() }, Encoder = JavaScriptEncoder.Create(UnicodeRanges.All), DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull };
|
||||
private static readonly JsonSerializerOptions _options = new() { WriteIndented = true, Converters = { new JsonStringEnumConverter(), new FightTaskStageResetModeInvalidToIgnoreConverter (), new FightTaskStageResetModeConverter() }, Encoder = JavaScriptEncoder.Create(UnicodeRanges.All), DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull };
|
||||
|
||||
// TODO: 参考 ConfigurationHelper ,拆几个函数出来
|
||||
private static readonly Lazy<Root> _rootConfig = new(() => {
|
||||
|
||||
@@ -21,7 +21,7 @@ public enum FightStageResetMode
|
||||
Current,
|
||||
|
||||
/// <summary>
|
||||
/// 无效关卡
|
||||
/// 忽略 / 不变
|
||||
/// </summary>
|
||||
Invalid,
|
||||
Ignore,
|
||||
}
|
||||
|
||||
@@ -212,7 +212,7 @@ public class ConfigConverter
|
||||
ConfigurationHelper.DeleteValue(ConfigurationKeys.HideUnavailableStage);
|
||||
ConfigurationHelper.DeleteValue(ConfigurationKeys.CustomStageCode);
|
||||
ConfigurationHelper.DeleteValue(ConfigurationKeys.UseAlternateStage);
|
||||
fightTask.StageResetMode = fightTask.UseOptionalStage ? FightStageResetMode.Invalid : FightStageResetMode.Current;
|
||||
fightTask.StageResetMode = fightTask.HideUnavailableStage ? FightStageResetMode.Current : FightStageResetMode.Ignore;
|
||||
|
||||
if (fightTask.Series > 6)
|
||||
{
|
||||
|
||||
@@ -1426,7 +1426,7 @@ public class AsstProxy
|
||||
&& (Instances.TaskQueueViewModel.TaskItemViewModels.FirstOrDefault(t => t.TaskId == taskId)?.Index ?? -1) is int index and > -1
|
||||
&& index <= ConfigFactory.CurrentConfig.TaskQueue.Count
|
||||
&& ConfigFactory.CurrentConfig.TaskQueue[index] is Configuration.Single.MaaTask.FightTask fight
|
||||
&& FightTask.GetFightStage(fight.StagePlan) is "Annihilation")
|
||||
&& FightTask.GetFightStage(fight) is "Annihilation")
|
||||
{
|
||||
Instances.TaskQueueViewModel.AddLog("AnnihilationStage, " + LocalizationHelper.GetString("GiveUpUploadingPenguins"));
|
||||
break;
|
||||
|
||||
@@ -748,7 +748,7 @@ Do not adjust the proxy multiplier setting in the game</system:String>
|
||||
<!--<system:String x:Key="CurrentStage">Current Stage</system:String>-->
|
||||
<!--<system:String x:Key="LastBattle">Last Battle</system:String>-->
|
||||
<system:String x:Key="DefaultStage">Cur/Last</system:String>
|
||||
<system:String x:Key="InvalidStage">Invalid</system:String>
|
||||
<!--<system:String x:Key="InvalidStage">Invalid</system:String>-->
|
||||
<system:String x:Key="ClosedStage">The event is not open</system:String>
|
||||
<system:String x:Key="UnsupportedStages">Unsupported stages</system:String>
|
||||
<system:String x:Key="LowVersion">Old Version, Update required</system:String>
|
||||
|
||||
@@ -749,7 +749,7 @@ C:\\leidian\\LDPlayer9
|
||||
<!--<system:String x:Key="CurrentStage">当前关卡</system:String> -->
|
||||
<!--<system:String x:Key="LastBattle">上次作战</system:String>-->
|
||||
<system:String x:Key="DefaultStage">現在/前回</system:String>
|
||||
<system:String x:Key="InvalidStage">無効なレベル</system:String>
|
||||
<!--<system:String x:Key="InvalidStage">無効なレベル</system:String>-->
|
||||
<system:String x:Key="ClosedStage">ステージが未公開か既に終了している</system:String>
|
||||
<system:String x:Key="UnsupportedStages">未サポートステージ</system:String>
|
||||
<system:String x:Key="LowVersion">バージョンの更新が必要</system:String>
|
||||
|
||||
@@ -750,7 +750,7 @@ C:\\leidian\\LDPlayer9
|
||||
<!--<system:String x:Key="CurrentStage">현재 스테이지</system:String>
|
||||
<system:String x:Key="LastBattle">최근 작전</system:String>-->
|
||||
<system:String x:Key="DefaultStage">현재/최근</system:String>
|
||||
<system:String x:Key="InvalidStage">잘못된 스테이지</system:String>
|
||||
<!--<system:String x:Key="InvalidStage">잘못된 스테이지</system:String>-->
|
||||
<system:String x:Key="ClosedStage">미개방 스테이지</system:String>
|
||||
<system:String x:Key="UnsupportedStages">미지원 스테이지</system:String>
|
||||
<system:String x:Key="LowVersion">낮은 버전</system:String>
|
||||
|
||||
@@ -749,7 +749,7 @@ C:\\leidian\\LDPlayer9。\n
|
||||
<!--<system:String x:Key="CurrentStage">当前关卡</system:String> -->
|
||||
<!--<system:String x:Key="LastBattle">上次作战</system:String>-->
|
||||
<system:String x:Key="DefaultStage">当前/上次</system:String>
|
||||
<system:String x:Key="InvalidStage">无效关卡</system:String>
|
||||
<!--<system:String x:Key="InvalidStage">无效关卡</system:String>-->
|
||||
<system:String x:Key="ClosedStage">活动未开放</system:String>
|
||||
<system:String x:Key="UnsupportedStages">不支持的关卡</system:String>
|
||||
<system:String x:Key="LowVersion">版本过低</system:String>
|
||||
|
||||
@@ -749,7 +749,7 @@ C:\\leidian\\LDPlayer9\n
|
||||
<!--<system:String x:Key="CurrentStage">目前關卡</system:String>-->
|
||||
<!--<system:String x:Key="LastBattle">上次作戰</system:String>-->
|
||||
<system:String x:Key="DefaultStage">目前/上次</system:String>
|
||||
<system:String x:Key="InvalidStage">無效關卡</system:String>
|
||||
<!--<system:String x:Key="InvalidStage">無效關卡</system:String>-->
|
||||
<system:String x:Key="ClosedStage">活動未開放</system:String>
|
||||
<system:String x:Key="UnsupportedStages">不支援的關卡</system:String>
|
||||
<system:String x:Key="LowVersion">版本過低</system:String>
|
||||
|
||||
@@ -92,7 +92,7 @@ public class FightSettingsUserControlModel : TaskSettingsViewModel
|
||||
{ "炭", "SK-5" },
|
||||
};
|
||||
|
||||
private readonly StageSourceItem InvalidStage = new() { Display = LocalizationHelper.GetString("InvalidStage"), Value = "__INVALID__", IsOpen = false, IsVisible = false };
|
||||
/* private readonly StageSourceItem InvalidStage = new() { Display = LocalizationHelper.GetString("InvalidStage"), Value = "__INVALID__", IsOpen = false, IsVisible = false };*/
|
||||
|
||||
public ObservableCollection<StagePlanItem> StagePlan { get => field; set => SetAndNotify(ref field, value); } = [];
|
||||
|
||||
@@ -151,7 +151,23 @@ public class FightSettingsUserControlModel : TaskSettingsViewModel
|
||||
public bool CustomStageCode
|
||||
{
|
||||
get => GetTaskConfig<FightTask>().IsStageManually;
|
||||
set => SetTaskConfig<FightTask>(t => t.IsStageManually == value, t => t.IsStageManually = value);
|
||||
set {
|
||||
bool ret = SetTaskConfig<FightTask>(t => t.IsStageManually == value, t => t.IsStageManually = value);
|
||||
if (ret && !value)
|
||||
{
|
||||
var stagePlan = GetTaskConfig<FightTask>().StagePlan;
|
||||
for (int i = 0; i < stagePlan.Count; i++)
|
||||
{
|
||||
var stage = stagePlan[i];
|
||||
if (!Instances.StageManager.GetStageList().Any(p => p.Value == stage))
|
||||
{
|
||||
stagePlan[i] = string.Empty;
|
||||
}
|
||||
}
|
||||
SetTaskConfig<FightTask>(t => t.StagePlan.SequenceEqual(stagePlan), t => t.StagePlan = stagePlan);
|
||||
RefreshCurrentStagePlan();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -490,7 +506,7 @@ public class FightSettingsUserControlModel : TaskSettingsViewModel
|
||||
if (value)
|
||||
{
|
||||
HideUnavailableStage = false;
|
||||
StageResetMode = FightStageResetMode.Invalid;
|
||||
StageResetMode = FightStageResetMode.Ignore;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -569,7 +585,7 @@ public class FightSettingsUserControlModel : TaskSettingsViewModel
|
||||
public List<GenericCombinedData<FightStageResetMode>> StageResetModeList { get; } =
|
||||
[
|
||||
new() { Display = LocalizationHelper.GetString("DefaultStage"), Value = FightStageResetMode.Current },
|
||||
new() { Display = LocalizationHelper.GetString("InvalidStage"), Value = FightStageResetMode.Invalid },
|
||||
new() { Display = LocalizationHelper.GetString("NotSwitch"), Value = FightStageResetMode.Ignore },
|
||||
];
|
||||
|
||||
public FightStageResetMode StageResetMode
|
||||
@@ -636,11 +652,16 @@ public class FightSettingsUserControlModel : TaskSettingsViewModel
|
||||
return value;
|
||||
}
|
||||
|
||||
public static string? GetFightStage(IEnumerable<string> stageNames)
|
||||
public static string? GetFightStage(FightTask fightTask)
|
||||
{
|
||||
var list = stageNames.Where(i => i != Instance.InvalidStage.Value);
|
||||
var stage = list.FirstOrDefault(Instances.TaskQueueViewModel.IsStageOpen);
|
||||
stage ??= list.FirstOrDefault();
|
||||
if (fightTask == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var list = fightTask.StagePlan;
|
||||
var stage = list?.FirstOrDefault(Instances.TaskQueueViewModel.IsStageOpen);
|
||||
stage ??= list?.FirstOrDefault();
|
||||
return stage;
|
||||
}
|
||||
|
||||
@@ -711,7 +732,6 @@ public class FightSettingsUserControlModel : TaskSettingsViewModel
|
||||
{
|
||||
return SerializeTask(fight, Instances.TaskQueueViewModel.TaskItemViewModels[index].TaskId);
|
||||
}
|
||||
_logger.Error("Failed to set fight params: current task is not in the task queue.");
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -728,7 +748,7 @@ public class FightSettingsUserControlModel : TaskSettingsViewModel
|
||||
}
|
||||
|
||||
using var scope = _lock.EnterScope();
|
||||
var stage = GetFightStage(fight.StagePlan);
|
||||
var stage = GetFightStage(fight);
|
||||
if (stage is null)
|
||||
{
|
||||
return null;
|
||||
@@ -792,19 +812,24 @@ public class FightSettingsUserControlModel : TaskSettingsViewModel
|
||||
RefreshStageList();
|
||||
foreach (var task in ConfigFactory.CurrentConfig.TaskQueue.OfType<FightTask>().Where(i => !i.IsStageManually))
|
||||
{
|
||||
var originalPlan = task.StagePlan.ToList();
|
||||
bool reset = false;
|
||||
for (int i = 0; i < task.StagePlan.Count; i++)
|
||||
{
|
||||
var stage = task.StagePlan[i];
|
||||
if (stage != InvalidStage.Value && !stageList.Any(p => p.Value == stage))
|
||||
if (!stageList.Any(p => p.Value == stage))
|
||||
{
|
||||
task.StagePlan[i] = task.StageResetMode switch {
|
||||
FightStageResetMode.Current => string.Empty,
|
||||
FightStageResetMode.Invalid => InvalidStage.Value,
|
||||
_ => string.Empty,
|
||||
};
|
||||
_logger.Information("Reset non-existing stage from plan: {Stage} to {}", stage, task.StagePlan[i]);
|
||||
reset = true;
|
||||
if (task.StageResetMode == FightStageResetMode.Current)
|
||||
{
|
||||
task.StagePlan[i] = string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (reset)
|
||||
{
|
||||
_logger.Information("Reset non-existing stage: {} to {}", string.Join(", ", originalPlan), string.Join(", ", task.StagePlan));
|
||||
}
|
||||
}
|
||||
RefreshCurrentStagePlan();
|
||||
});
|
||||
@@ -822,11 +847,10 @@ public class FightSettingsUserControlModel : TaskSettingsViewModel
|
||||
var listSource = stageList.Select(i => new StageSourceItem() { Display = i.Display, Value = i.Value, IsVisible = !HideUnavailableStage || i.IsStageOpen(Instances.TaskQueueViewModel.CurDayOfWeek), IsOpen = Instances.StageManager.GetStageList().FirstOrDefault(p => p.Value == i.Value)?.IsStageOpen(Instances.TaskQueueViewModel.CurDayOfWeek) ?? true }).ToList();
|
||||
|
||||
// 补过期关卡进来
|
||||
foreach (var item in listCurrent.Where(i => i != InvalidStage.Value && !listSource.Any(p => p.Value == i)))
|
||||
foreach (var item in listCurrent.Where(i => !listSource.Any(p => p.Value == i)))
|
||||
{
|
||||
listSource.Add(new StageSourceItem() { Display = item, Value = item, IsOpen = false, IsVisible = false });
|
||||
listSource.Add(new StageSourceItem() { Display = item, Value = item, IsOpen = false, IsVisible = false, IsOutdated = true });
|
||||
}
|
||||
listSource.Add(InvalidStage); // 无效关卡
|
||||
listSource.FirstOrDefault(i => i.Value == "Annihilation")?.Display = current.UseCustomAnnihilation ? (AnnihilationModeList.FirstOrDefault(i => i.Value == current.AnnihilationStage).Key ?? LocalizationHelper.GetString("Annihilation.Current")) : LocalizationHelper.GetString("Annihilation.Current");
|
||||
StageListSource = new ObservableCollection<StageSourceItem>(listSource);
|
||||
current.StagePlan = listCurrent; // StageListSource更新后, 恢复StagePlan
|
||||
@@ -935,6 +959,11 @@ public class FightSettingsUserControlModel : TaskSettingsViewModel
|
||||
public bool IsOpen { get => field; set => SetAndNotify(ref field, value); } = true;
|
||||
|
||||
public bool IsVisible { get => field; set => SetAndNotify(ref field, value); } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether 过期活动关卡, 加删除线
|
||||
/// </summary>
|
||||
public bool IsOutdated { get; set; } = false;
|
||||
}
|
||||
|
||||
public class StagePlanItem(string stage = "") : PropertyChangedBase
|
||||
@@ -958,18 +987,12 @@ public class FightSettingsUserControlModel : TaskSettingsViewModel
|
||||
return;
|
||||
}
|
||||
|
||||
if (value == Instance.InvalidStage.Value)
|
||||
{
|
||||
IsOpen = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
IsOpen = Instances.StageManager.GetStageList().FirstOrDefault(p => p.Value == value)?.IsStageOpen(Instances.TaskQueueViewModel.CurDayOfWeek) ?? true;
|
||||
}
|
||||
IsOpen = Instances.StageManager.GetStageList().FirstOrDefault(p => p.Value == value)?.IsStageOpen(Instances.TaskQueueViewModel.CurDayOfWeek) ?? true;
|
||||
Instance.SetFightParams();
|
||||
}
|
||||
} = stage;
|
||||
|
||||
public bool IsOpen { get => field; set => SetAndNotify(ref field, value); } = true;
|
||||
// 仅供 ComboBox本身 和 手写Stage的TextBlock 绑定使用
|
||||
public bool IsOpen { get => field; set => SetAndNotify(ref field, value); } = Instances.TaskQueueViewModel.IsStageOpen(stage);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,7 +196,7 @@ public class MallSettingsUserControlModel : TaskSettingsViewModel
|
||||
var fightStageEmpty = ConfigFactory.CurrentConfig.TaskQueue
|
||||
.OfType<FightTask>()
|
||||
.Where(task => task.IsEnable is not false)
|
||||
.Any(task => string.IsNullOrEmpty(FightSettingsUserControlModel.GetFightStage(task.StagePlan)));
|
||||
.Any(task => string.IsNullOrEmpty(FightSettingsUserControlModel.GetFightStage(task)));
|
||||
var task = new AsstMallTask() {
|
||||
CreditFight = CreditFightTaskEnabled && !fightStageEmpty,
|
||||
FormationIndex = CreditFightSelectFormation,
|
||||
|
||||
@@ -266,28 +266,43 @@
|
||||
Margin="-10,0,0,0">
|
||||
<!-- 当 CustomStageCode 为 false 时显示 ComboBox -->
|
||||
<ComboBox
|
||||
DisplayMemberPath="Display"
|
||||
ItemsSource="{Binding StageListSource, Source={x:Static ui_vms:TaskQueueViewModel.FightTask}}"
|
||||
Opacity="{c:Binding 'IsOpen ? 1 : 0.5'}"
|
||||
ScrollViewer.CanContentScroll="False"
|
||||
SelectedValue="{Binding Stage}"
|
||||
SelectedValuePath="Value"
|
||||
Visibility="{c:Binding !CustomStageCode,
|
||||
Source={x:Static ui_vms:TaskQueueViewModel.FightTask}}">
|
||||
|
||||
<ComboBox.ItemContainerStyle>
|
||||
<Style BasedOn="{StaticResource ComboBoxItemBaseStyle}" TargetType="ComboBoxItem">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsVisible}" Value="False">
|
||||
<Setter Property="Visibility" Value="Collapsed" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding IsOpen}" Value="False">
|
||||
<Setter Property="Opacity" Value="0.4" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding IsOpen}" Value="True">
|
||||
<Setter Property="Opacity" Value="1" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</ComboBox.ItemContainerStyle>
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Display}">
|
||||
<TextBlock.Style>
|
||||
<Style TargetType="TextBlock">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsOutdated}" Value="True">
|
||||
<Setter Property="TextDecorations" Value="Strikethrough" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding IsOpen}" Value="False">
|
||||
<Setter Property="Opacity" Value="0.5" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding IsOpen}" Value="True">
|
||||
<Setter Property="Opacity" Value="1" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</TextBlock.Style>
|
||||
</TextBlock>
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
|
||||
<!-- 当 CustomStageCode 为 true 时显示 TextBox -->
|
||||
|
||||
Reference in New Issue
Block a user