2016-09-09 3 views
0

WPF를 사용하는 응용 프로그램의 UI를 개발하고 있습니다. 명령 바인딩을 사용하고 있습니다. 명령은 버튼이 윈도우 안에있을 때 올바르게 작동합니다. 하지만 UserControl 내 버튼을 넣으면 명령 매개 변수가 null입니다.ContentControl을 사용할 때만 매개 변수가 null입니다.

뷰 모델 코드 :

 public RelayCommand<Window> MainCommand { get; private set; } 
     private void MainAction(Window window) 
     { 
      // here the parameter is null 
      if (window == null) return; 
      MainPage main = new MainPage(); 
      main.Show(); 
      window.Close(); 
     } 

사용자 제어 :

<UserControl x:Class="Kitchen.UI.View.HeaderFooter" 
       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:Kitchen.UI.View" 
       mc:Ignorable="d" 
       d:DesignHeight="300" d:DesignWidth="300"> 
     <UserControl.Resources> 
      <ResourceDictionary> 
       <ResourceDictionary.MergedDictionaries> 
        <ResourceDictionary Source="../Skins/MainSkin.xaml"/> 
       </ResourceDictionary.MergedDictionaries> 
      </ResourceDictionary> 
     </UserControl.Resources> 

     <UserControl.Template> 
      <ControlTemplate TargetType="UserControl"> 
       <Grid DataContext="{Binding DataContext, RelativeSource={RelativeSource TemplatedParent}}"> 
        <Grid.RowDefinitions> 
         <RowDefinition Height="Auto"></RowDefinition> 
         <RowDefinition Height="*"></RowDefinition> 
         <RowDefinition Height="Auto"></RowDefinition> 
        </Grid.RowDefinitions> 
        <Grid.ColumnDefinitions> 
         <ColumnDefinition Width="*"></ColumnDefinition> 
         <ColumnDefinition Width="Auto"></ColumnDefinition> 
         <ColumnDefinition Width="*"></ColumnDefinition> 
        </Grid.ColumnDefinitions> 

        <ScrollViewer Grid.Column="1" Grid.Row="1" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"> 
         <ContentControl Content="{TemplateBinding Content}"/> 
        </ScrollViewer> 
        <Image Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="3" Source="{StaticResource HeaderImage}" 
        Margin="0 10 0 0" HorizontalAlignment="Stretch" SizeChanged="Image_SizeChanged" IsHitTestVisible="False"></Image> 
        <Image Grid.Column="0" Grid.Row="3" Grid.ColumnSpan="3" Source="{StaticResource FooterImage}" 
        Margin="0 -1 0 10" HorizontalAlignment="Stretch" Height="Auto"></Image> 


       </Grid> 
      </ControlTemplate> 
     </UserControl.Template> 

    </UserControl> 

나는 사용자 정의 컨트롤 내부의 버튼을 넣어하는 방법 :

<Window xmlns:View="clr-namespace:Kitchen.UI.View" x:Class="Kitchen.UI.View.Order" Name="OWindow" ResizeMode="NoResize" WindowState="Maximized" 
     WindowStartupLocation="CenterOwner" WindowStyle="None " 
     Width="1600" 
     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:ignore="http://www.galasoft.ch/ignore" 
     mc:Ignorable="d ignore" 
     DataContext="{Binding Order, Source={StaticResource Locator}}"> 



    <View:HeaderFooter x:Name="HeaderFooter"> 
     <Button Grid.Row="1" Grid.Column="0" 
       Command="{Binding ShowExitCommand}" 
         CommandParameter="{Binding ElementName=OWindow}" 
       Style="{StaticResource ImageButtonStyle}"> 
       <Grid> 
        <Grid.RowDefinitions> 
         <RowDefinition ></RowDefinition> 
        </Grid.RowDefinitions> 
        <Grid.ColumnDefinitions> 
         <ColumnDefinition Width="*"></ColumnDefinition> 
        </Grid.ColumnDefinitions> 
        <Image Grid.Column="0" Grid.Row="0" Source="{StaticResource ButtonBack}" Width="180" Grid.ColumnSpan="2" /> 
        <TextBlock Grid.Column="1" Grid.Row="0" Text="مشاهده سفارشات خارج شده از صف" Style="{StaticResource ImageButtonTextBlockStyle}" FontSize="15"/> 
       </Grid> 
     </Button> 
    </View:HeaderFooter> 
</Window> 
+0

아래 내 대답은 null 매개 변수의 문제를 해결합니다. 이제는 물론 usercontrol이 포함 된 창을 usercontrol에 전달할 수 없다는 점을 인정해야합니다. 명확하고 불가능한 순환 종속성입니다 .-) 아래에서 올바른 데모/예를 제안했습니다. 질문을 수정하여 목표를 명확히하고 테스트 후 답변을 수락하고 필요한 경우 별도의 후속 질문을하십시오. –

+0

순환 의존성이 아니며 순환 참조이며 프로그래밍 개념에서 런타임 중에 처리 할 수 ​​있으며 '가능'합니다. 우리가 어떤 객체 안에 'this'참조를 사용하는 것처럼. – Alto

답변

1

x:Reference 대신 ElementName로 시도, 이 이어야합니다. 요소 참조 해결을 위해 language-level support을 가져오고, 해당 ElementName (프레임 워크 수준에서 작동하는)은 해결할 수 없습니다.

CommandParameter="{Binding Source={x:Reference OWindow}}" 

순환 의존성을 방지하기 위해, 당신은 위의 예는 명확하게

<Grid > 
    <DataGrid Name="OWindow" Width="10" Height="10"/> 

    <local:HeaderFooter x:Name="HeaderFooter"> 
    <Button Grid.Row="1" Grid.Column="0" 
      Command="{Binding ShowExitCommand}" 
        CommandParameter="{Binding Source={x:Reference OWindow} }" 
      > <!-- instead of ElementName=OWindow --> 

을 유의하시기 바랍니다 예를 들어, 사용자 컨트롤 자체의 용기없는 무언가를, 참조 할 필요가 내 대답은 일관된 맥락에서 문제를 정확하게 해결하는 반면, 순환 참조는 수정해야 할 원래 코드의 또 다른 문제 일뿐입니다.

+0

순환 참조가 발생했습니다. – Alto

+0

@Alto 창에는 사용자 정의 컨트롤이 포함되어 있기 때문에 분명하지만 컨테이너가 아닌 다른 참조를 사용하면 * 작동합니다. 다른 문제에 도움이 필요하면 답을 수락하고 구체적인 후속 질문을하십시오. –

+0

이제 진리를 가져 왔습니다. 네 말이 맞지만 너의 자랑스러워. 고맙습니다! – Alto

0

마지막으로 문제를 해결했습니다. 템플릿을 여러 창에 적용해야하므로 UserControl을 사용했고 UserControl의 내용 내에서 매개 변수로 UserControl을 포함하는 창에 대한 참조를 전달하고 싶지 않으면 템플릿으로 성공했습니다. .

이제 사용자 정의 ControlTemplate을 적용하여 현재 작동 중입니다.

그러나 이것은 WPF의 버그 또는 적어도 아키텍처 취약점이라고 생각합니다. Window 자체 또는 그리드와 같은 다른 컨트롤에서 {Binding ElementName=OWindow}을 사용하면 참조가 처리되고 처리되지만 사용자 정의 사용자 정의 컨트롤 내에서 참조를 사용하면 null 참조가 발생합니다.

저는 이것이 Window 구성에서 매개 변수를 캡처하기 때문에라고 생각합니다.

+0

매개 변수가 캡처 된 가설에 대한 나의 업 보이트. 또한 내 대답을 수락 해 주셔서 감사 드리며 너무 자랑스러워서 미안합니다. –

관련 문제