WPF: TreeViewItem связал с ICommand

Я занят, создавая мое первое приложение MVVM в WPF.

В основном проблема, которую я имею, состоит в том, что у меня есть TreeView (Система. Windows. Средства управления. TreeView), который я поместил на свое Окно WPF, я имею, решают, что я свяжу с ReadOnlyCollection объектов CommandViewModel, и эти объекты состоят из DisplayString, Тега и RelayCommand.

Теперь в XAML, у меня есть свой TreeView, и я успешно связал свой ReadOnlyCollection с этим. Я могу просмотреть это, и все выглядит хорошо в UI.

Проблема теперь - то, что я должен связать RelayCommand с Командой TreeViewItem, однако от того, что я вижу, что TreeViewItem не имеет Команды. Это вынуждает меня сделать это в свойстве IsSelected или даже в Коде позади метода TreeView_SelectedItemChanged или является там способом сделать это волшебно в WPF?

Это - код, который я имею:

<TreeView BorderBrush="{x:Null}" 
      HorizontalAlignment="Stretch" 
      VerticalAlignment="Stretch">
<TreeView.Items>
    <TreeViewItem
        Header="New Commands"
        ItemsSource="{Binding Commands}"
        DisplayMemberPath="DisplayName"
        IsExpanded="True">
    </TreeViewItem>
</TreeView.Items>

и идеально я хотел бы просто пойти:

<TreeView BorderBrush="{x:Null}" 
      HorizontalAlignment="Stretch" 
      VerticalAlignment="Stretch">
<TreeView.Items>
    <TreeViewItem
        Header="New Trade"
        ItemsSource="{Binding Commands}"
        DisplayMemberPath="DisplayName"
        IsExpanded="True"
        Command="{Binding Path=Command}">
    </TreeViewItem>
</TreeView.Items>

Делает у кого-то есть решение, которое позволяет мне использовать инфраструктуру RelayCommand, которую я имею.

Спасибо парни, очень ценившие!

Richard

9
задан Richard 15 February 2010 в 15:20
поделиться

3 ответа

Самый простой способ сделать это, и его дешевый, это получить бумажную человеческую страницу для cscope и создать текстовый файл... например:

$ man cscope | col -b > cscope.txt 

Или, чтобы преобразовать в ps файл для передачи в Ghostscript:

$ man -t cscope > cscope.ps
$ gs cscope.ps -sOutputFile=cscope.pdf
-121--4460139-

Я согласен, если вы попытаетесь поместить MireItemSeparator в, он пожалуется, что только MireItem может быть дочерним, когда GWT пытается создать виджет. Поскольку в настоящее время это не поддерживается, я предлагаю вам запросить это в качестве будущего расширения для команды GWT.

Тем временем можно добавить разделитель программным способом и добавить команду следующим образом: XML-файл:

<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder" xmlns:g="urn:import:com.google.gwt.user.client.ui">
<g:HTMLPanel>
    <g:MenuBar ui:field="menuBar">
        <g:MenuItem ui:field="helpMenuItem">Help</g:MenuItem>
        <g:MenuItem ui:field="aboutMenuItem">About</g:MenuItem>
        <g:MenuItem ui:field="siteMapMenuItem">Site Map</g:MenuItem>
    </g:MenuBar>
</g:HTMLPanel>

Java-файл (ы):

public class Menu extends Composite {
...
@UiField MenuBar menuBar;
@UiField MenuItem helpMenuItem;
...
public Menu() {
    initWidget(uiBinder.createAndBindUi(this));
    // insert a separator
    menuBar.insertSeparator(1);
    // attach commands to a menu item
    helpMenuItem.setCommand(new MenuCommand(HistoryToken.Help));
    ...
}  

public class MenuCommand implements Command {
    final HistoryToken historyToken;

    public MenuCommand(HistoryToken historyToken) {
        this.historyToken = historyToken;
    }

    @Override
    public void execute() {
        historyToken.fire();
    }
}  

public enum HistoryToken {
    Help,About,SiteMap;

    public void fire(){
        History.newItem(this.toString());
    }
}


В другом месте моего кода я реализовал HistiveListener , чтобы уловить любые изменения, т.е.

class HistoryManager implements ValueChangeHandler<String> {
    // 1. get token
    // 2. change it into a HistoryToken
    // 3. perform switch statement 
    // 4. change contents based upon HistoryToken found
...
}  
-121--4244906-

Спасибо за ввод в проблему, и да, я сказал, что не хочу, чтобы за решением стоял код, однако в то время я так что я в итоге воспользовался событием TreeView_SelectedItemChanged.

Хотя подход Уилла кажется хорошей работой вокруг, для моей личной ситуации я решил, что буду использовать код позади. Причина этого заключается в том, что представление и XAML останутся такими же, как если бы TreeViewItem имел свойство «Command», к которому может быть привязана команда. Теперь мне не нужно изменять шаблоны или представления, все, что мне нужно сделать, это добавить код и событие для TreeView_SelectedItemChanged.

Мое решение:

  private void TreeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
    {
        if (sender != null)
        {
            var treeView = sender as TreeView;
            if (treeView != null)
            {
                var commandViewModel = treeView.SelectedItem as CommandViewModel;
                if (commandViewModel != null)
                {
                    var mi = commandViewModel.Command.GetType().GetMethod("Execute");
                    mi.Invoke(commandViewModel.Command, new Object[] {null});
                }
            }
        }
    }

Поскольку к TreeViewItem уже присоединена команда RelayCommand, все, что я сейчас делаю, это просто вручную вызвать метод «Execute» для этой конкретной команды RelayCommand.

Если это совершенно неправильный способ сделать это, пожалуйста, дайте мне знать...

Спасибо!

2
ответ дан 4 December 2019 в 07:47
поделиться

Это хороший пример того, как MVVM сильно пострадали в WPF. Вы ожидаете, что для некоторых элементов графического интерфейса будет поддержка Command, но ее нет, поэтому вы вынуждены пройти сложный процесс (как показано в примере Уилла) только для того, чтобы прикрепить команду к чему-либо.

Будем надеяться, что они исправят это в WPF 2.0: -)

0
ответ дан 4 December 2019 в 07:47
поделиться

Я бы сделал заголовок TreeViewItem как кнопку, а затем скинул бы кнопку так, чтобы она не ' не выглядеть или действовать как один, а затем выполнить привязку моей команды к кнопке.

Возможно, вам придется сделать это с помощью DataTemplate или изменить шаблон самого TreeViewItem. Никогда этого не делал, но вот как я делал похожие вещи (например, заголовки вкладок).


Вот пример того, о чем я говорю (вы можете бросить это в Kaxaml и поэкспериментировать с ним):

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
   <Page.Resources>
      <Style x:Key="ClearButan" TargetType="Button">
         <Setter Property="Template">
            <Setter.Value>
               <ControlTemplate TargetType="Button">              
                 <Border Name="border"
                     Padding="4"
                     Background="transparent">
                     <Grid >
                     <ContentPresenter HorizontalAlignment="Center"
                                    VerticalAlignment="Center">
                     </ContentPresenter>
                     </Grid>
                 </Border>
               </ControlTemplate>
            </Setter.Value>
         </Setter>
      </Style>
   </Page.Resources>
   <Grid>
      <TreeView>
         <TreeViewItem>
            <Button Style="{StaticResource ClearButan}">
            easy peasy
            </Button>
         </TreeViewItem>
      </TreeView>
   </Grid>
</Page>

Я создал новый четкий стиль для кнопки. Затем я просто вставляю кнопку в TVI и устанавливаю ее стиль. Конечно, вы можете сделать то же самое с помощью шаблонов данных.

1
ответ дан 4 December 2019 в 07:47
поделиться
Другие вопросы по тегам:

Похожие вопросы: