Создание одного элемента ListBoxItem

У меня есть существующее решение моего пользовательского интерфейса WPF, но его реализация ViewModel неуклюжа, и я хочу ее улучшить.

Ниже показано, как работает моя текущая система:

  • Есть Current Task (примечание: только один элемент)
  • Есть Task List для задач (примечание: возможно много), которые необходимо запустить в будущем.
  • Когда пользователь выбирает один список, другой выбор удаляется

Два списка

Проблема в том, что я реализую Current Task как список только с одним элементом. Это означает, что мне нужно таскать с собой резервный IList для ItemSource и другое свойство для SelectedItem.

Есть ли другой элемент управления, который я могу использовать, чтобы вести себя как ListBoxItem, но я могу привязать свою CurrentTask напрямую к нему, и мне не придется возиться со списком для ItemSource?

EDIT: Чтобы выбор исчезал при выборе одного списка, у меня есть триггер, настроенный на событие SelectionChanged.


person Killnine    schedule 11.09.2014    source источник
comment
Используйте TextBlock и привяжите его свойство Text.   -  person Rohit Vats    schedule 11.09.2014
comment
@Rohit: OP запрашивает элемент управления, реализующий функциональность HideSelection, встроенную в ListBoxes, ListViews и т. д. Недостаточно просто отображать текст.   -  person Michael Gunter    schedule 11.09.2014
comment
@RohitVats: Да, я хотел бы привязать его ко всему объекту TaskDto и просто показать текст в элементе управления, используя DataTemplate или что-то в этом роде. Я думал просто реализовать ListBoxItem, но застрял.   -  person Killnine    schedule 11.09.2014


Ответы (2)


(удален мой предыдущий ответ)

Мне приходит в голову, что по крайней мере часть функций, которые вы ищете, реализуется классом RadioButton. Несколько RadioButtons в одной и той же области действия гарантируют, что выбран только один из них. Вероятно, вам придется проделать небольшую работу, чтобы убедиться, что ваши RadioButtons могут корректно отображаться в вашем пользовательском интерфейсе, и вам, вероятно, потребуется переделать некоторые вещи, чтобы получить именно тот пользовательский интерфейс, который вам нужен. Кроме того, RadioButton не имеет свойства SelectedItem/SelectValue, в которое он может выполнять запись, поскольку WPF не предоставляет встроенного механизма для безопасной привязки нескольких элементов управления к свойству SelectedWhatever. Но вы можете довольно легко реализовать это самостоятельно с помощью кода программной части или триггеров.

person Michael Gunter    schedule 11.09.2014
comment
Это отличный момент. Я даже не думал об элементе управления RadioButton. Группы позволят ему автоматически сохранять только один выбранный элемент. Но я согласен, это, вероятно, приносит с собой изрядное количество других изменений. Поскольку я так близок к своей текущей реализации, я, вероятно, не рискну этим путем, но это может быть полезно для будущего пользователя. - person Killnine; 11.09.2014

Вот реализация, с которой я пошел:

Просмотр XAML

<!-- The Current Task box -->
<ListBox x:Name="CurrentTaskBox" FlowDirection="RightToLeft" Background="{StaticResource WhiteBrush}">
    <ListBoxItem IsSelected="{Binding CurrentTaskSelected, Mode=TwoWay}" Content="{Binding CurrentTask.TaskId}">
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="Selected">
                <command:EventToCommand Command="{Binding SetTaskDetailsFromCurrentTaskCommand}"/>
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </ListBoxItem>
</ListBox>

<!-- The Task List box -->
<ListBox x:Name="TaskListBox" SelectedIndex="{Binding TaskListIndex}" SelectedValue="{Binding TaskListSelection}" IsSynchronizedWithCurrentItem="True" HorizontalContentAlignment="Stretch" ItemsSource="{Binding TaskList}" FlowDirection="RightToLeft" DisplayMemberPath="TaskId" Margin="3">
   <i:Interaction.Triggers>
       <i:EventTrigger EventName="SelectionChanged">
            <command:EventToCommand Command="{Binding SetTaskDetailsFromTaskListCommand}" CommandParameter="{Binding SelectedItem, ElementName=TaskListBox}"/>
       </i:EventTrigger>
    </i:Interaction.Triggers>
</ListBox>

Модель представления

/* Omitted most INPC property declarations...kinda boring */

public ICommand SetTaskDetailsFromCurrentTaskCommand { get { return new RelayCommand(SetTaskDetailsFromCurrentTask); } }
public ICommand SetTaskDetailsFromTaskListCommand { get { return new RelayCommand<TaskScheduleSequenceDto>(async taskSelection => await SetTaskDetailsFromTaskList(taskSelection)); } }


private bool _currentTaskSelected;
public bool CurrentTaskSelected
{
    get
    {
        return _currentTaskSelected;
    }
    set
    {
        Set(() => CurrentTaskSelected, ref _currentTaskSelected, value);
    }
}

private async Task SetTaskDetailsFromTaskList(TaskScheduleSequenceDto taskListSelection)
{
    if (taskListSelection == null)
    {
        return;
    }

    var taskDetails = await _broker.RetrieveTaskDetails(taskListSelection.TaskId);

    TaskDetails = taskDetails;
    CurrentTaskSelected = false;
}

private void SetTaskDetailsFromCurrentTask()
{
    TaskDetails = CurrentTask;
    TaskListSelection = null;
    CurrentTaskSelected = true;
}

Это отлично работает и требует только, чтобы у меня было одно свойство CurrentTask на моей виртуальной машине, что, как мне кажется, намного чище.

person Killnine    schedule 11.09.2014