仅在使用ContentControl时参数为null

时间:2016-09-09 09:11:56

标签: c# wpf

我正在使用WPF为应用程序开发UI。我正在使用命令绑定。当按钮放在窗口内时,命令可以正常工作。但是当我将按钮放在UserControl中时,命令参数为空。

ViewModel代码:

        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>

2 个答案:

答案 0 :(得分: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   -->

请注意,上面的示例清楚地表明我的答案正确地解决了问题在一致的上下文中,而循环引用只是要修复的原始代码的另一个问题。

答案 1 :(得分:0)

最后,我改变了问题。我需要一个模板应用于几个窗口,所以我使用了UserControl并且它作为模板成功,除非我想将UserControl的包含窗口的引用作为参数传递给UserControl内容中的命令。

现在我将自定义ControlTemplate应用于Window,它现在正在运行。

但我认为这是一个错误或至少是WPF的架构弱点。当您在Window本身或其他控件(如Grid)中使用{Binding ElementName=OWindow}时,将解析并处理引用,但如果您在用户定义的用户控件中使用它,则会导致空引用。

我认为这是因为他们正在Window构造中捕获参数。