2016-09-09 9 views
0

Ich entwickle UI für eine Anwendung mit WPF. Ich verwende die Befehlsbindung. Der Befehl funktioniert ordnungsgemäß, wenn die Schaltfläche in das Fenster eingefügt wird. Aber wenn ich den Button in mein UserControl setze, ist der Befehlsparameter null.Parameter ist nur Null bei Verwendung von ContentControl

Ansichtsmodell Code:

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

Die Benutzersteuerung:

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

Die Art und Weise ich die Taste in der Steuer Benutzer setzen:

<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

Meine Antwort unten behebt das Problem eines Null-Parameters. Nun müssen Sie natürlich zugeben, dass Sie kein Fenster mit der Benutzersteuerung an die Benutzersteuerung selbst übergeben können: Es ist eine klare, unmögliche Kreisabhängigkeit :-) Ich habe unten eine korrekte Demo/ein Beispiel vorgeschlagen. Bearbeiten Sie die Frage, um Ihr Ziel zu verdeutlichen. Bitte akzeptieren Sie die Antwort nach dem Testen und stellen Sie bei Bedarf eine separate Folgefrage. –

+0

Es ist keine zirkuläre Abhängigkeit, es ist eine zirkuläre Referenz und in Programmierkonzepten kann es während der Laufzeit behandelt werden und es ist sicherlich 'möglich'. Genauso wie wir 'diese' Referenz in jedem Objekt verwenden. – Alto

Antwort

1

mit x:Reference Versuchen statt ElementName, diese sollte Bring language-level support für Element Referenzauflösung, die ElementName (die auf der Framework-Ebene arbeitet) kann möglicherweise nicht auflösen.

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

eine zyklische Abhängigkeit zu vermeiden, müssen Sie etwas verweisen, das nicht der Behälter der Benutzersteuerung selbst, zum Beispiel

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

Bitte beachten Sie, dass das obige Beispiel macht deutlich, dass mein Antwort löst das Problem korrekt in einem konsistenten Kontext, während der Zirkelverweis nur ein weiteres Problem des ursprünglichen Codes ist, der behoben werden muss.

+0

Es verursachte zyklische Referenz. – Alto

+0

@Alto Das ist klar, da das Fenster das Benutzersteuerelement enthält, aber wenn Sie die Referenz von etwas verwenden, das kein Container ist, funktioniert * es *. Bitte akzeptieren Sie die Antwort und stellen Sie eine spezifische Folgefrage, wenn Sie Hilfe für eine andere Angelegenheit benötigen. –

+0

Jetzt haben Sie die Wahrheit gebracht. Dein richtiger aber dein so stolz. Vielen Dank! – Alto

0

Endlich habe ich mich durch das Problem verändert. Ich brauchte eine Vorlage, die auf mehrere Fenster angewendet werden konnte, daher verwendete ich ein UserControl und es war erfolgreich als Vorlage, wenn ich nicht den Verweis des umschließenden Fensters des UserControl als Parameter an einen Befehl aus dem Inhalt des UserControl übergeben wollte .

Jetzt eine benutzerdefinierte ControlTemplate auf das Fenster anwenden und es funktioniert jetzt.

Aber ich denke, das ist ein Bug oder zumindest eine architektonische Schwäche für WPF. Wenn Sie {Binding ElementName=OWindow} aus dem Fenster selbst oder anderen Steuerelementen wie Grid verwenden, wird der Verweis aufgelöst und verarbeitet, aber wenn Sie ihn innerhalb des benutzerdefinierten Benutzersteuerelements verwenden, wird der Nullverweis verursacht.

Ich denke, das liegt daran, dass sie den Parameter bei der Fensterkonstruktion erfassen.

+0

Mein Upvote für Ihre Hypothese darüber, wann der Parameter erfasst wird. Danke auch für die Annahme meiner Antwort und es tut mir leid wenn ich zu "stolz" aussehe .. –

Verwandte Themen