2016-10-03 3 views
0

오늘 아침 나는 here이라는 질문을했고 간단한 작업 샘플을 사용하여 예상보다 다른 동작을 보였습니다.DataBinding이 UserControl에 전파되지 않는 이유

GitHub에서 전체 작동 샘플. 아래의 주요 부분 코드.

이 경우이 명령은 UserControl이 Window의 자식으로 직접 사용되는 경우에도 모든 UserControl에 전파되지 않습니다. 또한 UserControl이 ListBox ItemTemplate에 대한 DataTemplate으로 사용되는 경우에도 작동하지 않습니다.

또한 Command가 UserControls에 도달하는 문제를 해결하기위한 해킹 버튼이 포함되어 있습니다. 해킹은 StackOverflow에서 온 것입니다.

그러나 해킹을 사용하면 UserControl이 명령을받지 못하는 이유를 설명 할 수 없으며이 해킹을 사용하면 좋은 코딩의 첫 번째 규칙 인 "안녕 응집력 및 낮은 결합력"도 손상됩니다. 해킹은 UserControl에서 Command를 관리하기 위해 윈도우 코드에서 사용되어야합니다. 기본적으로 발생해야한다고 생각합니다.

왜 명령이 기본적으로 UserControl에 전파되지 않으며 사용자 정의 컨트롤에 명령을 깨끗하게 전파하려면 어떻게해야합니까?

참고 : CommandBinding 하나만 사용하면 UserControl에서 하나만 제거해도 문제가 해결되지 않습니다.

부분 코드 :

<Window x:Class="CommandRoutingIntoItemTemplate.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:local="clr-namespace:CommandRoutingIntoItemTemplate" 
     xmlns:system="clr-namespace:System;assembly=mscorlib" 
     mc:Ignorable="d" 
     Title="MainWindow" Height="350" Width="525"> 
    <Grid> 
     <Grid.RowDefinitions> 
      <RowDefinition></RowDefinition> 
      <RowDefinition></RowDefinition> 
      <RowDefinition Height="Auto"></RowDefinition> 
     </Grid.RowDefinitions> 

     <local:UserControlTest></local:UserControlTest> 

     <ListBox Grid.Row="1"> 
      <ListBox.ItemTemplate> 
       <DataTemplate> 
        <Border BorderBrush="Aqua" BorderThickness="2"> 
         <local:UserControlTest></local:UserControlTest> 
        </Border> 
       </DataTemplate> 
      </ListBox.ItemTemplate> 

      <ListBox.Items> 
       <system:String>1</system:String> 
       <system:String>2</system:String> 
      </ListBox.Items> 
     </ListBox> 

     <StackPanel Grid.Row="2" Orientation="Horizontal"> 
      <Button Command="local:Commands.CommandTest">Put focus on TestBlock and click here to see if command occurs</Button> 
      <Button Click="AddHack">Hack</Button> 
     </StackPanel> 
    </Grid> 
</Window> 

UserControl을 : 당신은 사용자 정의 컨트롤에서 호출 명령을받지 못하고있다

<UserControl x:Class="CommandRoutingIntoItemTemplate.UserControlTest" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:local="clr-namespace:CommandRoutingIntoItemTemplate" 
      mc:Ignorable="d" 
      d:DesignHeight="300" d:DesignWidth="300"> 
    <UserControl.CommandBindings> 
     <CommandBinding Command="local:Commands.CommandTest" CanExecute="CommandTestCanExecuteUserControl" Executed="CommandTestExecuteUserControl"></CommandBinding> 
    </UserControl.CommandBindings> 
    <Grid> 
     <TextBox Text="UserControlTest"> 
      <TextBox.CommandBindings> 
       <CommandBinding Command="local:Commands.CommandTest" CanExecute="CommandTestCanExecuteTextBox" Executed="CommandTestExecuteTextBox"></CommandBinding> 
      </TextBox.CommandBindings> 
     </TextBox> 
    </Grid> 
</UserControl> 

답변

1

그 이유는 당신의 버튼을 별도의 초점 범위에 있지 않은 것입니다. WPF가 명령 대상의 포커스 요소를 올바르게 선택하려면 명령 호출 컨트롤과 별도의 포커스 범위에 있어야합니다.

프레임 워크는 포커스 범위에서 명령 바인딩을 찾는 단추에서 시각적 트리를 트래버스합니다 (사용자의 경우에는 찾을 수 없습니다). 프레임 워크가 현재 포커스 범위에서 명령 바인딩을 찾지 못하면 포커스가있는 요소의 부모 포커스 범위를 조사합니다 (부모 범위가없는 Window 포커스 범위에있는 버튼의 경우 검색이 끝납니다).

StackPanelFocusManager.IsFocusScope="True"을 설정하면 문제가 해결됩니다.

단추에 CommandTarget 속성을 지정하여 사용자 정의 컨트롤을 가리키고 포커스를 사용하지 않을 수도 있습니다.

+0

위대한 설명! 감사합니다! 완벽하게 작동합니다. UserControl 측에서 항상 모든 유형의 사용법에서 항상 작동하는지 확인하기 위해 무언가를 할 수 있는지 알고 있습니까? 지금은 문제가 없지만 다른 곳에서는 UserControl을 사용하고 싶습니다. 그런 생각을 기억해야합니다. 그것은 모든 상황에서 적절한 사용을 보장하기 위해 단 하나의 일반적인 장소 (UserControl)에서 코드를 작성하는 더 나은 솔루션 소리가 난다? –

+0

또한 menuItem으로 테스트했는데, Menu 요소가 나에게 제안한 픽스를 가지고 있기 때문에 잘 동작 할 것입니다 : FocusManager.IsFocusScope가 true로 설정 되었습니까? 그게 내가 알아야 할 기억이다 ;-)? –

+0

@EricOuellet 맞습니다. MenuItem은 자신의 포커스 범위가있는 팝업으로 표시됩니다. – ghord