自动将窗口宽度和高度设置为ItemsControl项

时间:2016-07-12 17:49:59

标签: c# wpf

我有一个基本窗口,它充当UserControls的通用容器。它按预期工作,除了宽度和高度似乎不是由子项的大小决定的(宽度和高度设置为auto,我希望)。基本窗口的xaml如下:

<local:BaseView x:Class="Program.UI.Views.BaseWindowView"
            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:Program.UI.Views"
            xmlns:converters="clr-namespace:Program.UI.Converters"
            xmlns:presenter="clr-namespace:Program.Presenter"
            xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
            mc:Ignorable="d" 
            ResizeMode="NoResize" WindowStyle="None"
            d:DesignHeight="300" d:DesignWidth="300" AllowsTransparency="True">
<i:Interaction.Triggers>
    <i:EventTrigger EventName="Closing">
        <presenter:EventToCommand Command="{Binding Mode=OneWay, Path=CloseWindow}" PassEventArgsToCommand="True"/>
    </i:EventTrigger>
</i:Interaction.Triggers>    
<local:BaseView.Resources>
    <ResourceDictionary>
        <converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
        <converters:SystemEventToForegroundColor x:Key="SystemEventToForegroundColor" />
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="/Program;component/UI/Templates/Generic.xaml"/>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</local:BaseView.Resources>
<local:BaseView.Foreground>
    <SolidColorBrush Color="Black" Opacity="100"/>
</local:BaseView.Foreground>
<local:BaseView.Background>
    <SolidColorBrush Color="White" Opacity="0"/>
</local:BaseView.Background>
<Border BorderBrush="#FF838383" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" BorderThickness="1" Height="auto" Width="auto" Margin="0,0,5,5">
    <Canvas Background="#E8F6F6" HorizontalAlignment="Stretch"  VerticalAlignment="Stretch" Height="auto" Width="auto">
        <Canvas.Effect>
            <DropShadowEffect RenderingBias="Quality" Opacity="0.3" ShadowDepth="3" BlurRadius="4"/>
        </Canvas.Effect>
        <DockPanel VerticalAlignment="Stretch" HorizontalAlignment="Stretch" 
                   Margin="0,0,0,0" x:Name="ReferenceInfo" Canvas.Left="0" Canvas.Top="0"
                   Width="{Binding ActualWidth, ElementName=InfoCanvas}"
                   Height="{Binding ActualHeight, ElementName=InfoCanvas}"
                   d:DesignWidth="294"
                   d:DesignHeight="294">

            <Grid Width="auto" Height="auto" HorizontalAlignment="Stretch"  VerticalAlignment="Stretch">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                </Grid.RowDefinitions>
                <Grid Grid.Row="0" Width="auto" HorizontalAlignment="Stretch" Height="30" VerticalAlignment="Top">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition />
                        <ColumnDefinition Width="30" />
                    </Grid.ColumnDefinitions>
                    <Border Grid.Column="0" BorderBrush="#FF838383" BorderThickness="0,0,0,1" Height="30" VerticalAlignment="Top">
                        <Label Style="{StaticResource WindowHeaderControlTitle}" MouseDown="Label_MouseDown"/>
                    </Border>
                    <Border Grid.Column="1" BorderBrush="#FF838383" BorderThickness="1,0,0,1">
                        <Label Style="{StaticResource WindowHeaderControlCloseLabel}" MouseEnter="Label_MouseEnter" MouseLeave="Label_MouseLeave" MouseLeftButtonUp="Label_MouseLeftButtonUp" MouseLeftButtonDown="Label_MouseLeftButtonDown" FontSize="14" FontFamily="Segoe UI Black" FontStretch="UltraExpanded" Content="X"/>
                    </Border>
                </Grid>
                <ItemsControl Grid.Row="1" Height="auto" Width="auto" ItemsSource="{Binding ChildView}"/>
            </Grid>

        </DockPanel>
    </Canvas>
</Border>

视图是在Excel功能区按钮的单击事件上生成的,其代码隐藏为:

var childView = new DatapointDefinitionsView();
childView.DataContext = new DatapointDefinitionsViewModel();

ApplicationData.Presenter.ShowView<BaseWindowView>(
    new BaseWindowViewModel(childView, ApplicationData.Presenter), true);

ShowView代码是:

    private BaseWindowView _windowView;
    public void ShowView<T>(BaseWindowViewModel viewModel, bool asModal) where T : BaseWindowView, new()
    {
        _windowView = new T
        {

            DataContext = viewModel,
            ShowInTaskbar = false,
            Title = viewModel.Caption,

        };
        //Width = viewModel.ChildView[0].Width,
        //Height = viewModel.ChildView[0].Height
        if (asModal)
        {
            _windowView.ShowDialog();
            _windowView = null;
        }
        else
        {
            _windowView.Show();
        }
    }

将宽度和高度明确设置为子高度会将宽度设置为指定的宽度,但不会影响高度。但是,即使它确实如此,这也不是一个令人满意的解决方案,因为它意味着值是固定的,并且如果用户控件尺寸发生变化则不会更新。

还有另一种方法可以达到我的目的吗?

1 个答案:

答案 0 :(得分:0)

所以我最终能够解决这个问题,具有所有所需的功能,如下所示:

我将画布高度(在xaml中)绑定到DockPanel的高度 Height="{Binding ElementName=ReferenceInfo, Path=ActualHeight}"

但是ItemsControl元素的宽度 Width="{Binding ElementName=ChildUserControl, Path=ActualWidth}"

我从DockPanel中删除了高度和宽度,并根据@lokusking早先的建议重新启用了SizeToContent="WidthAndHeight"窗口属性。

为了启用CanResizeWithGrip功能(并且让子usercontrol的内容相应地动态调整大小),我挂钩了窗口SizeChanged事件并添加了以下代码:

    private void BaseView_SizeChanged(object sender, SizeChangedEventArgs e)
    {
        var window = sender as Window;

        if (ChildUserControl.HasItems)
        {
            var chlidControl = ChildUserControl.Items[0] as UserControl;
            var context = (BaseWindowViewModel)window.DataContext;

            // Ignore the first 3 resize events - these occur on view generation
            if (!context.InitialResizeComplete)
                if (context.ResizeOperations < 3)
                {
                    context.ResizeOperations++;
                    return;
                }

            context.InitialResizeComplete = true;

            // Subtract all fixed size elements from window dimensions
            chlidControl.Width = window.ActualWidth - (OuterBorder.BorderThickness.Left + OuterBorder.BorderThickness.Right + OuterBorder.Margin.Right + OuterBorder.Margin.Left);
            chlidControl.Height = window.ActualHeight - (OuterBorder.BorderThickness.Top + OuterBorder.BorderThickness.Bottom + OuterBorder.Margin.Top + OuterBorder.Margin.Bottom + TaskBarGrid.Height);
        }
    }

我还没决定最初的3个调整大小操作的驱动因素。我的第一个猜测是初始化,然后是x,然后是y - 但是反思它可能是1为baseview,1为basewindow,1为usercontrol。如果是这种情况,那么使用这种方法附加的用户控件本身有多个视图可能会出现问题,但我还没有测试过。

希望有人能发现这有用,感谢那些提供帮助的人。