2010-02-15 7 views
9

WPF에서 첫 번째 MVVM 응용 프로그램을 만드는 중입니다.WPF : ICommand에 바인딩 된 TreeViewItem

기본적으로 내가 겪고있는 문제는 WPF 창에 배치 한 TreeView (System.Windows.Controls.TreeView)가 있고 CommandViewModel 항목의 ReadOnlyCollection에 바인딩 할 것을 결정했으며 항목은 DisplayString, Tag 및 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 인프라를 사용합니다.

감사합니다. , 버튼을 수 보이게하거나 하나처럼 행동을 선택한 후 버튼에 바인딩 내 명령을 수행하지 않도록 한 후 버튼을 피부에 TreeViewItem의 the Header를 설정 내가 할 줄

리처드

답변

2

문제에 입력 주셔서 감사합니다, 그래, 나는 그러나 나는 아직도 그 당시, 솔루션 뒤에 코드를 싶지 않은 말 했는가 나는 단순히 뭔가를 놓친다는 인상 아래서 ... 그래서 TreeView_SelectedItemChanged 이벤트를 사용하게되었습니다.

비록 윌의 접근 방식이 좋은 일로 보일지라도, 개인적인 상황 때문에 코드를 뒤에서 사용할 것이라고 결정했습니다. 그 이유는 TreeViewItem에 내 Command를 바인딩 할 수있는 "Command"속성이있는 경우 View 및 XAML이 그대로 유지되기 때문입니다. 이제 Templates 또는 Views를 변경할 필요가 없습니다. TreeView_SelectedItemChanged에 대한 코드와 이벤트를 추가하면됩니다.

내 솔루션 : 나는 이미 TreeViewItem에 부착 된 RelayCommand을 때, 내가 지금 뭐하는 거지 모두가 단지 수동으로 특정 RelayCommand에서 "실행"메소드를 호출하는 것입니다

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}); 
       } 
      } 
     } 
    } 

.

이 그때 알려 주시기 바랍니다 그것에 대해가는 완전히 잘못된 방법 ...

감사 인 경우!

+1

저는 ASP.NET treeview를 사용하여 TreeView와 TreeViewItem을 확장하여 이러한 종류의 기능을 추가 할 수 있다고 생각합니다. TVI를 변경하여 필요한 것을 추가 한 다음 TV에서 메소드를 오버로드하여 TVI의 새 인스턴스를 만듭니다. WPF 트리 뷰에서 동일한 패턴을 사용할 수 있는지 여부는 알 수 없습니다. 나는 철저히 검사하지는 않았다. – Will

1

.

DataTemplate을 통해이 작업을 수행해야하거나 TreeViewItem 자체의 템플릿을 변경해야 할 수 있습니다. 한번도 해본 적이 없지만, 비슷한 일을했습니다 (예 : 탭 페이지 헤더). 내가 단추를위한 새로운 명확한 스타일을 만든

<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> 

:


는 여기에 내가 (당신이 Kaxaml이 드롭과 함께 놀러 수) 무슨 말인지의 예입니다. 그런 다음 TVI에 단추를 놓고 스타일을 설정합니다. 물론 데이터 템플릿을 사용하여 동일한 작업을 수행 할 수 있습니다.

+0

안녕하세요, 저는 여러분이하고 싶은 것을 보았습니다. 빠른 응답에 감사드립니다.하지만이게 가장 좋은 해결책입니까? 나는 높고 낮은 그물을 수색하고 그것을하는 좋은 방법을 찾을 수 없다! 그게 짜증나는 말인가?이게 그냥 내장되어 있지 않다는 얘기 야. 적어도이 방법을 제공했는데, 지금 어떻게하면 단추와 바운드 텍스트를 보여줄 헤더를 얻을 수 있을까? – Richard

+0

@richard가 샘플 – Will

+1

으로 업데이트되었습니다. 업데이트에 대한 감사의 뜻을 전하면 이것이 작동 할 것입니다. 나는 다른 길로 갔지만 도움을 많이 주셔서 감사합니다. 바라기를 이것은이 문제를 가진 다른 누군가를 도울 것입니다. – Richard

0

이것은 MVVM이 WPF에서 매우 많은 애프터 - 한 생각의 좋은 예입니다. 특정 gui 아이템에 대한 명령 지원이있을 것으로 기대하지만, 그렇지 않습니다. 따라서 명령에 뭔가를 첨부하기 위해 정교한 프로세스 (예 : Will의 예와 같이)를 수행해야합니다. 그들이 WPF에서이 문제를 해결

하자 희망 2.0 :-)는

+4

MVVM은 WPF 이후에 나왔기 때문에 정확히 "사후 검토"가 아니 었습니다. MVC의 원칙을 WPF에 적용하는 방법이었습니다. 또한, 이것은 WPF의 treeview의 단점입니다. 트리 뷰는 이런 종류의 사용을 위해 개발되지 않았으며, 다소 근시안적이었습니다. – Will

23

나는 이것이 전에 "대답했다"는 것을 알고 있지만, 그 대답이 이상적이지 않았기 때문에 나는 내 두 센트를 넣을 것이라고 생각했다. 나는 "스타일있는 버튼 속임수"에 의지하거나 코드 숨김을 사용하지 않고 MVVM에서의 모든 분리를 유지할 수있는 방법을 사용합니다. 당신의 XAML 헤더 추가에

<i:Interaction.Triggers> 
    <i:EventTrigger EventName="SelectedItemChanged"> 
     <i:InvokeCommandAction Command="{Binding TreeviewSelectedItemChanged}" CommandParameter="{Binding ElementName=treeView, Path=SelectedItem}"/> 
    </i:EventTrigger> 
</i:Interaction.Triggers> 

:

xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" 

을 다음 프로젝트에 위의 어셈블리에 대한 참조를 추가해야합니다 당신의 트 리뷰에서 다음 XAML을 추가합니다.

그 후에 모든 것은 버튼이나 뭐 다른 명령과 똑같이 작동합니다.

+0

+1 - 이것은 코드 숨김 해결책이 아니기 때문에 좋은 대답입니다. 그러나 이것은 즉시 사용 가능한 솔루션이 아닙니다. ( – TheCloudlessSky

+0

'System.Windows.Interactivity'가 재배포 가능합니까? – AMissico

+0

예, "C : \ Program Files (x86) \ Microsoft SDKs \ Expression \ Blend \"를 참조하십시오. NET Framework \ v4.0 \ Redist.en.txt " – AMissico