2014-01-22 2 views
0

사용자 지정 컨트롤 인 "GameIconControl"의 인스턴스가 여러 개있는 랩 패널이 있습니다. 내 목표는 사용자 지정 컨트롤을 두 번 클릭하면 랩 패널에서 제거되도록하는 것입니다.사용자 지정 컨트롤을 두 번 클릭 이벤트를 MainViewModel 명령에 바인딩

랩 패널은 ObservableCollection에 바인딩됩니다.

다음은 사용자 지정 컨트롤 xaml입니다. 더블 클릭 명령 바인딩을 추가하려고 시도했지만 랩 패널에로드 된 명령을 찾는 방법을 알지 못합니다. 실험으로, MainViewModel이 각 GameIconControl을로드 할 때 MainViewModel이 명령이있는 곳이기 때문에 "각각"에 대한 DataContext를 설정하려고했습니다. 불운.

<Style TargetType="{x:Type assets:GameIconControl}"> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="{x:Type assets:GameIconControl}"> 
       <Border Margin="3" 
         Background="Transparent" 
         BorderBrush="{TemplateBinding BorderBrush}" 
         BorderThickness="{TemplateBinding BorderThickness}"> 
        <StackPanel HorizontalAlignment="Center" 
           VerticalAlignment="Center" 
           Orientation="Vertical"> 

         <Image Source="{TemplateBinding Icon}" /> 
         <ContentPresenter Height="Auto" 
              Margin="3" 
              HorizontalAlignment="Center" 
              ContentSource="GameName" /> 
        </StackPanel> 
         <i:Interaction.Triggers> 
          <i:EventTrigger EventName="MouseDoubleClick"> 
           <command:EventToCommand Command="{Binding MoveGameIconToGamesList, Mode=OneWay}" /> 
          </i:EventTrigger> 
         </i:Interaction.Triggers> 
       </Border> 

      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

컨트롤의 코드는 매우 단순합니다. 세 명의 DP 및 생성자 :

static GameIconControl() 
    { 
     DefaultStyleKeyProperty.OverrideMetadata(typeof(GameIconControl), new FrameworkPropertyMetadata(typeof(GameIconControl))); 
    } 

    public GameIconControl(){} 

    public GameIconControl(string name, BitmapImage icon) 
    { 
     Icon = icon; 
     GameName = name; 
    } 

    public GameIconControl(string name, BitmapImage icon, Game game) { 
     GameForControl = game; 
     Icon = icon; 
     GameName = name; 
    } 

    public const string IconPropertyName = "Icon"; 
    public const string GameNamePropertyName = "GameName"; 
    public const string GamePropertyName = "Game"; 


    public string GameName 
    { 
     get { return (string)GetValue(GameNameProperty); } 
     set { SetValue(GameNameProperty, value); } 
    } 

    public static readonly DependencyProperty GameNameProperty = 
     DependencyProperty.Register(GameNamePropertyName, typeof(string), typeof(GameIconControl), new UIPropertyMetadata(default(string))); 


    public BitmapImage Icon 
    { 
     get { return (BitmapImage)GetValue(IconProperty); } 
     set { SetValue(IconProperty, value); } 
    } 

    public static readonly DependencyProperty IconProperty = 
     DependencyProperty.Register(IconPropertyName, typeof(BitmapImage), typeof(GameIconControl), new PropertyMetadata(default(BitmapImage))); 


    public Game GameForControl 
    { 
     get { return (Game)GetValue(GameProperty); } 
     set { SetValue(GameProperty, value); } 
    } 

    public static readonly DependencyProperty GameProperty = 
     DependencyProperty.Register(GamePropertyName, typeof(Game), typeof(GameIconControl), new PropertyMetadata(default(Game))); 
} 

모든 도움을 주실 수 있습니다.

마지막으로 xaml이 열립니다. MVVM Lite를 사용하고 있습니다.

<Window x:Class="Saved_Game_Backup.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:cc="clr-namespace:Saved_Game_Backup.Assets" 
    xmlns:command="http://www.galasoft.ch/mvvmlight" 
    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" 
    xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit" 
    xmlns:viewModel="clr-namespace:Saved_Game_Backup.ViewModel" 
    DataContext="{Binding Path=Main, 
          Source={StaticResource Locator}}"> 
+1

시도 바인딩 'RelativeSource FindAncestor'를 사용하는 (http://stackoverflow.com/a/1127964/2998271). 그게 당신이 컨트롤의 부모 DataContext에 바인딩 할 수 있지만 귀하의 경우처럼 스타일 내에서 그것을 시도하지 않았습니다. – har07

답변

1

미안하지만, 당신이 그것을 모든 잘못하고 있어요. WPF에서는 데이터 항목을 처리하지만 UI 요소는이 아닙니다. 시나리오를 만들려면 데이터 유형 클래스 (INotifyPropertyChanged interface을 구현)를 만든 다음 UI의 클래스 인스턴스가 어떻게 표시되는지 정의하는 DataTemplate을 선언하면됩니다. 귀하의 경우 DataTemplate은 a GameIconControl입니다. 이러한 클래스의 컬렉션을 컬렉션 컨트롤의 ItemsSource 속성에 바인딩하면 Framework에서 모든 렌더링 작업을 수행합니다.

이 방법을 사용하면 DataTemplate에서보기 모델의 Command으로 직접 바인딩 할 수 있으며 UserControl의 속성에 데이터 바인딩을 시도하는 데 문제가 없습니다. UI에서 항목을 제거하려면보기 모델에서 항목을 컬렉션에서 제거하면 UI가 자동으로 업데이트됩니다.

향후 참조를 위해 일반적으로 이 아닌UserControlDataContext을 그대로 사용하는 것이 좋습니다.오히려 그렇게하는 대신이 같은 RelativeSource Binding 사용 UserControl DependencyProperty들에 액세스 할 수 또한

<TextBlock Text="{Binding PropertyName, RelativeSource={RelativeSource AncestorType={ 
    x:Type views:Saved_Game_Backup.MainWindow}}}" /> 

을하면 내지 속성이나 Command에 결합 할 수있는 바람직 (a UserControl 설정된다DataContext 이런 제어) 외부 : [여기] 같이

<TextBlock Text="{Binding DataContext.PropertyName, RelativeSource={RelativeSource 
    AncestorType={x:Type views:Saved_Game_Backup.MainWindow}}}" /> 
+0

감사합니다. 컨트롤에 DataContext를 설정하려고 시도하는 것은 저의 경험이 없으므로 작동시키려는 시도였습니다. 나에게도 잘못된 것처럼 보였지만 어떻게 진행해야할지 확신이 서지 않았습니다. 이미 랩핑 패널에서 렌더링이 진행 중이었고 추가/제거가 잘되었지만 패널에서 두 번 클릭하는 것 이외의 다른 방법으로 렌더링이 진행되었습니다. – CubemonkeyNYC

1

저는 MainViewModel이 GameItemControl의 DataContext가 아니라고 생각합니다. 이 문제를 극복하기 위해 MainViewModel 용 StaticResource를 만들고이를 바인딩에 사용할 수 있습니다. 다음 코드 스 니펫이 도움이 될 것입니다.

<WrapPanel.Resources> 
     <local:MainViewModel x:Key="viewModel" /> 
    </WrapPanel.Resources> 

    <command:EventToCommand Command="{Binding MoveGameIconToGameList,Mode=OneWay,  

      Source={StaticResource viewModel}}" /> 

이 정보가 도움이되는지 알려주세요.

감사합니다, Riyaj Ahamed I

+0

이 내 xaml을 혼란스럽게합니다. 로컬 네임 스페이스가 없습니다. ViewModel은 네임 스페이스 "viewModel"에 있으므로, 을 강제하지만 여전히 깨지기 쉽습니다. 창문 xaml을 추가했습니다. – CubemonkeyNYC

관련 문제