0

我的主窗口HeightLeftTopWidth都通过样式绑定到它们各自的视图模型属性。我可以确认视图模型中的这四个属性仅分别设置为1920, 1920, 。1181080

但是当我启动应用程序时,主窗口上的TopWidth属性设置为其他值(Width将是1440并且Top将是通常小于的随机数300)。什么会导致这个?

这是我在窥探应用程序时看到的内容。注意如何TopWidth来自Local价值源:

清除/重置之前

奇怪的是,当我在 Snoop 中右键单击这些属性并告诉它“清除/重置”时,这些属性开始起作用。Snoop 正在做什么来解决这个问题?

清除/重置后

其他事实:

  • Top和viewmodel 属性的 getterWidth只在主窗口初始化时调用一次。堆栈跟踪贯穿框架绑定初始化代码。
  • Top和viewmodel 属性的设置器Width仅在 viewmodel 构造函数中调用一次,因为它将这些属性分别设置为1181080
  • 这四个属性的绑定都是双向的。
  • 这些都不会导致视图的属性改变/正确:
    • 在运行时更改关联的视图模型属性,即使在视图已完全加载之后也是如此。
    • 调用UpdateLayout()视图。
    • 调用InvalidateArrange()视图。
    • 调用InvalidateMeasure()视图。
    • 调用InvalidateProperty(FrameworkElement.WidthProperty)视图。
    • 调用InvalidateVisual()视图。
  • 我已经搜索和搜索,并且在任何地方都没有看到任何涉及视图TopWidth属性的代码(样式绑定除外)。

这里的风格:

样式中的绑定

抱歉,我不得不删掉类型名称和其他一些东西——这是一个公司应用程序。Window如果有帮助,则主窗口/视图位于其曾曾祖父的长继承线的末尾。我试图通过 MVVM-ing 使主窗口更易于重用——以前这些布局属性是在视图中的代码隐藏中设置的,并且视图具有构造函数参数:'(这与我需要键入样式的原因有关, 以及为什么样式基于其他东西。但是继承的类型都没有操纵布局属性。

PS 我看到其他人抱怨调整 WPF 的Window. 最常见的建议解决方案是绑定MinWidthMaxWidth以及Width. 当我这样做时,Width确实将其强制为我想要的值,但是您无法调整窗口大小,该Width属性仍然具有其Local值源,并且Top仍然不正确。

4

1 回答 1

0

鉴于"[Top] cannot be set through a style",并且考虑到绑定 Window.Width 的复杂性,我以不同的方式解决了这个问题。

我创建了这个名为的附加属性WindowLayout,并将其绑定到我的样式中的 viewmodel 属性:

public static class WindowLayoutBehavior
{
    public static readonly DependencyProperty LayoutProperty = DependencyPropertyHelpers.RegisterAttached(
        (Window x) => GetLayout(x),
        new PropertyMetadata(HandleLayoutChanged));

    private static void HandleLayoutChanged(
        DependencyObject d,
        DependencyPropertyChangedEventArgs e)
    {
        if (!(d is Window window))
            return;
        if (!(e.NewValue is Rect rect))
            return;
        window.Height = rect.Height;
        window.Left = rect.Left;
        window.Top = rect.Top;
        window.Width = rect.Width;
    }

    [AttachedPropertyBrowsableForType(typeof(Window))]
    public static Rect GetLayout(Window window) =>
        window.GetValue(LayoutProperty) is Rect rect
            ? rect
            : default;

    public static void SetLayout(Window window, Rect rect) =>
        window.SetValue(LayoutProperty, rect);
}

DependencyPropertyHelpers.RegisterAttached是一种速记辅助方法,用于以您可能期望的方式创建附加属性。

风格中的用法:

<Setter
    Property="WindowLayoutBehavior.Layout"
    Value="{Binding WindowLayout, Mode=OneWay}"/>

现在,当我窥探应用程序时HeightLeftTop、 和Width所有显示为具有Local值源,并且当 viewmodel 属性更改时它们会更改,因此这对我有用。

于 2018-09-12T14:38:52.567 回答