根据子属性设置MinWidth和MinHeight形式

时间:2010-02-26 09:55:08

标签: wpf mvvm

我正在使用MVVM模式在WPF中编写应用程序。在我的应用程序中,我有一个IPopupWindowService,我用它来创建一个弹出对话框窗口。

因此,要在弹出窗口中显示ViewModel,您可以执行以下操作:

var container = ServiceLocator.Current.GetInstance<IUnityContainer>();
var popupService = container.Resolve<IPopupWindowService>();
var myViewModel = container.Resolve<IMyViewModel>();
popupService.Show((ViewModelBase)myViewModel);

这一切都很好。我想要做的是能够将MinHeightMinWidth设置为绑定到View的{​​{1}},并让弹出窗口使用这些设置,以便用户无法制作窗口小于其内容将允许。当用户缩小窗口时,内容会停止调整大小,但窗口不会。

修改

我将我的视图映射到ResourceDictionarys中的ViewModel,如下所示:

myViewModel

我的弹出视图如下所示:

<DataTemplate DataType="{x:Type ViewModels:MyViewModel}">
     <Views:MyView />
</DataTemplate>

2 个答案:

答案 0 :(得分:3)

您可以在ViewModel上定义MinHeightMinWidth属性,并使用数据绑定将View绑定到XAML中的那些属性:

<...
    MinHeight="{Binding Path=MinHeight}"
    MinWidth="{Binding Path=MinWidth}"
.../>

答案 1 :(得分:2)

我设计了完全相同的通用模态对话框控件(使用以类型为目标的DataTemplates),并且偶然发现了这个问题。

  • 使用RelativeSource不起作用,因为你只能找到那样的祖先(afaik)。

  • 另一种可能的解决方案是命名ContentPresenter并使用ElementName绑定绑定到该属性。但是,ContentPresenter不会从它呈现的Visual子级“继承”MinHeight和MinWidth属性。

解决方案最终是使用VisualTreeHelper在运行时获取与ViewModel关联的已解析View:

        DependencyObject lObj = VisualTreeHelper.GetChild(this.WindowContent, 0);
        if (lObj != null && lObj is FrameworkElement)
        {
            lWindowContentMinHeight = ((FrameworkElement)lObj).MinHeight;
            lWindowContentMinWidth = ((FrameworkElement)lObj).MinWidth;
        }

我将此代码放在ModalDialogView的代码隐藏中的OnActivated()覆盖中(在OnInitialized中,View还无法解析)。

唯一剩下的问题是纠正这些最小值,以便考虑窗口宽度和按钮面板高度。

<强>更新

以下是我在通用模态对话框中使用的代码。它解决了以下其他问题:

  • 正确地以所有者窗口为中心
  • 如果内容没有设置MinWidth和MinHeight,它什么都不做

    private bool _MinSizeSet = false;
    
    public ModalDialogView(object pDataContext)
        : this()
    {
        this.DataContext = pDataContext;
        this.LayoutUpdated += new EventHandler(ModalDialogView_LayoutUpdated);
    }
    
    void ModalDialogView_LayoutUpdated(object sender, EventArgs e)
    {
        if (System.Windows.Media.VisualTreeHelper.GetChildrenCount(this.WindowContent) > 0)
            SetInitialAndMinimumSize();
    }
    
    private void SetInitialAndMinimumSize()
    {
        FrameworkElement lElement = VisualTreeHelper.GetChild(this.WindowContent, 0) as FrameworkElement;
        if (!_MinSizeSet && lElement != null)
        {
            if (lElement.MinWidth != 0 && lElement.MinHeight != 0)
            {
                double lHeightDiff = this.ActualHeight - this.WindowContent.ActualHeight;
                double lWidthDiff = this.ActualWidth - this.WindowContent.ActualWidth;
                this.MinHeight = lElement.MinHeight + lHeightDiff;
                this.MinWidth = lElement.MinWidth + lWidthDiff;
                this.SizeToContent = SizeToContent.Manual;
                this.Height = this.MinHeight;
                this.Width = this.MinWidth;
                this.Left = this.Owner.Left + (this.Owner.ActualWidth - this.ActualWidth) / 2;
                this.Top = this.Owner.Top + (this.Owner.ActualHeight - this.ActualHeight) / 2;
            }
            _MinSizeSet = true;
        }
    }