2011-01-07 6 views
8

사용자가 목록 항목을 두 번 클릭하면 내 ViewModel에서 명령을 실행하기 위해 연결된 동작을 사용하려고합니다.ListViewItem에 대한 명령을 실행하기 위해 연결된 동작

본인은이 주제에 대한 기사를 검토 한 후 간단한 테스트 응용 프로그램을 만들려고했지만 여전히 문제가 있음을 예를 들어 설명합니다. Firing a double click event from a WPF ListView item using MVVM

내 간단한 테스트 뷰 모델은

여기
public class ViewModel 
{ 
    public ViewModel() 
    { 
     Stuff = new ObservableCollection<ListViewItem> 
        { 
         new ListViewItem { Content = "item 1" }, 
         new ListViewItem { Content = "item 2" } 
        }; 

     StringStuff = new ObservableCollection<string> { "item 1", "item 2" }; 
    } 

    public ObservableCollection<ListViewItem> Stuff { get; set; } 

    public ObservableCollection<string> StringStuff { get; set; } 

    public ICommand Foo 
    { 
     get 
     { 
      return new DelegateCommand(this.DoSomeAction); 
     } 
    } 

    private void DoSomeAction() 
    { 
     MessageBox.Show("Command Triggered"); 
    } 
} 

같은 수도 다른 예 당신입니다 연결된 속성입니다 ListViewItem이 유형의 목록을 반환 문자열의 목록과 다른 반환을이 명 컬렉션을 가지고 참조 :

public class ClickBehavior 
{ 
    public static DependencyProperty DoubleClickCommandProperty = DependencyProperty.RegisterAttached("DoubleClick", 
       typeof(ICommand), 
       typeof(ClickBehavior), 
       new FrameworkPropertyMetadata(null, new PropertyChangedCallback(ClickBehavior.DoubleClickChanged))); 

    public static void SetDoubleClick(DependencyObject target, ICommand value) 
    { 
     target.SetValue(ClickBehavior.DoubleClickCommandProperty, value); 
    } 

    public static ICommand GetDoubleClick(DependencyObject target) 
    { 
     return (ICommand)target.GetValue(DoubleClickCommandProperty); 
    } 

    private static void DoubleClickChanged(DependencyObject target, DependencyPropertyChangedEventArgs e) 
    { 
     ListViewItem element = target as ListViewItem; 
     if (element != null) 
     { 
      if ((e.NewValue != null) && (e.OldValue == null)) 
      { 
       element.MouseDoubleClick += element_MouseDoubleClick; 
      } 
      else if ((e.NewValue == null) && (e.OldValue != null)) 
      { 
       element.MouseDoubleClick -= element_MouseDoubleClick; 
      } 
     } 
    } 

    static void element_MouseDoubleClick(object sender, MouseButtonEventArgs e) 
    { 
     UIElement element = (UIElement)sender; 
     ICommand command = (ICommand)element.GetValue(ClickBehavior.DoubleClickCommandProperty); 
     command.Execute(null); 
    } 
} 

를 내 주 창에서 나는 첨부 된 동작을 설정하고 푸 명령에 결합 스타일을 정의

ListViewItems 정의 할 때
<Window.Resources> 
    <Style x:Key="listViewItemStyle" TargetType="{x:Type ListViewItem}"> 
     <Setter Property="local:ClickBehavior.DoubleClick" Value="{Binding Foo}"/>     
    </Style> 
</Window.Resources> 

617,451,515,잘 작동합니다 :

<!-- Works --> 
<Label Grid.Row="2" Content="DoubleClick click behaviour:"/>   
<ListView Grid.Row="2" Grid.Column="1" ItemContainerStyle="{StaticResource listViewItemStyle}"> 
    <ListViewItem Content="Item 3" /> 
    <ListViewItem Content="Item 4" /> 
</ListView> 

형 ListViewItem이 목록에 바인딩 할 때 너무 작동합니다

<!-- Works when items bound are of type ListViewItem --> 
<Label Grid.Row="3" Content="DoubleClick when bound to ListViewItem:"/>   
    <ListView Grid.Row="3" Grid.Column="1" ItemContainerStyle="{StaticResource listViewItemStyle}" ItemsSource="{Binding Stuff}">   
</ListView> 

을하지만 그렇지 않은 :

<!-- Does not work when items bound are not ListViewItem --> 
<Label Grid.Row="4" Content="DoubleClick when bound to string list:"/> 
    <ListView Grid.Row="4" Grid.Column="1" ItemContainerStyle="{StaticResource listViewItemStyle}" ItemsSource="{Binding StringStuff}"> 
</ListView> 

출력 창에 오류가 표시되지만 무엇이 잘못되었는지 이해하기 어렵습니다.
System.Windows.Data 오류 : 39 : BindingExpression 경로 오류 : 'Foo'속성이 'object' ''String '(HashCode = 785742638)'에 없습니다. BindingExpression : Path = Foo; DataItem = '문자열'(HashCode = 785742638); 대상 요소는 'ListViewItem'(Name = ''); 대상 속성은 'DoubleClick'(유형 'ICommand')

그래서 내 질문은 : 어떻게 ListViewItem 모델 개체의 목록에 바인딩 할 때 각 ListViewItem 올바르게 연결된 유선 얻을 수 있습니까?

감사합니다.

+0

이 매우 유용했다! 추가 된 재사용을 위해 ListViewItem 요소를 target = ListViewItem으로 변경했습니다. to Control 요소 = Control as target; –

답변

8

BindingDataContext은 문자열입니다. 문자열 클래스의 Foo 속성이 없으므로 오류가 발생합니다. 부모로부터 자신의 DataContext을 상속하기 때문에 다른 경우에는 발생하지 않습니다 (데이터 항목에 대해 자동 생성 컨테이너의 경우 - DataContext이 데이터 항목 임).

당신이 당신의 부모 ListViewDataContext를 사용하는 바인딩을 변경하는 경우

, 그것은 잘 작동합니다 :

Value="{Binding DataContext.Foo, RelativeSource={RelativeSource AncestorType={x:Type ListView}}}" 
+0

신속한 답변 주셔서 감사합니다, 아베. 당신은 스타이고 너무 오랫동안 이것을 알아 내려고 노력해 왔습니다. –

+1

폴 문제 없습니다. 바인딩 오류는 실제로는 암호화되어 있으며 때로는 어떤 일이 벌어지고 있는지보기 위해 새로운 쌍의 눈이 필요합니다! –

관련 문제