绑定到窗口高度和宽度的问题

问题描述 投票:0回答:11

当我尝试将窗口的高度和宽度绑定到视图模型中的属性时遇到一些问题。这是一个小示例应用程序来说明该问题。这是app.xaml.xs中的代码

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
       base.OnStartup(e);
        MainWindow mainWindow = new MainWindow();
        MainWindowViewModel mainWindowViewModel = new MainWindowViewModel();
        mainWindow.DataContext = mainWindowViewModel;
        mainWindow.Show();
    }
}

这是MainWindow.xaml:

<Window x:Class="TestApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Height="{Binding WindowHeight}" 
        Width="{Binding WindowWidth}"
        BorderThickness="{Binding WindowBorderThickness}">
</Window>

这是视图模型:

public class MainWindowViewModel
{
    public int WindowWidth { get { return 100; } }
    public int WindowHeight { get { return 200; } }
    public int WindowBorderThickness { get { return 8; } }
}

程序启动时,会调用 WindowHeight 和 WindowBorderThickness(但不是 WindowWidth)的 getter,因此窗口的高度和边框被正确设置,但宽度未被设置。

然后我添加按钮来触发所有属性的 PropertyChanged,这样视图模型现在看起来像这样:

public class MainWindowViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public void TriggerPropertyChanges()
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs("WindowWidth"));
            PropertyChanged(this, new PropertyChangedEventArgs("WindowHeight"));
            PropertyChanged(this, new PropertyChangedEventArgs("WindowBorderThickness"));
        }

    }

    public ICommand ButtonCommand { get { return new RelayCommand(delegate { TriggerPropertyChanges(); }); } }

    public int WindowWidth { get { return 100; } }
    public int WindowHeight { get { return 200; } }
    public int WindowBorderThickness { get { return 8; } }
}

现在,当我单击按钮时,将调用 WindowBorderThickness 的 getter,但不会调用 WindowWidth 和 WindowHeight 的 getter。对我来说,这一切都显得非常奇怪和不一致。我错过了什么?

c# .net wpf data-binding binding
11个回答
57
投票

尝试使用双向绑定,它对我有用:

Width="{Binding Path=xExt, Mode=TwoWay}"

13
投票

我遇到了同样的问题,我注意到这取决于 xaml 中首先写入高度还是宽度。如果高度优先,则绑定仅适用于它,反之亦然。解决方案是将绑定模式设置为“TwoWay”: 我所做的项目是使用 MS Studio 2010 和 .NET 4.0


12
投票

我会尝试回答我自己的问题。绑定正在工作,但我们不能真正确定布局系统是否要求例如窗口的宽度属性。

来自MSDN

如果此元素是其他元素中的子元素,则将此属性设置为一个值实际上只是一个建议值。布局系统以及父元素的特定布局逻辑将在布局过程中使用该值作为非绑定输入。实际上,FrameworkElement 几乎总是其他元素的子元素;即使您设置了窗口高度。 (对于 Window,当底层应用程序模型建立创建托管应用程序的 Hwnd 的基本渲染假设时,将使用该值。)

似乎有效的解决方案是将 WindowWidth 属性绑定到 MinWidth 和 MaxWidth 以及 Width。其中之一将被检索,至少在我上面使用的测试场景中是这样。


6
投票

好的,

我遇到了同样的问题,无法通过 XAML 将窗口尺寸(最小、最大、正常)正确绑定到我的视图模型。

我不知道为什么,但如果您通过代码而不是 XAML 来实现所有这些绑定,则没有任何问题。

这是我有效的 C# 代码:

this.SetBinding(Window.WidthProperty, new Binding("Width") { Source = MyViewModel, Mode=BindingMode.TwoWay });
this.SetBinding(Window.HeightProperty, new Binding("Height") { Source = MyViewModel, Mode=BindingMode.TwoWay });
this.SetBinding(Window.MaxWidthProperty, new Binding("MaxWidth") { Source = MyViewModel });
this.SetBinding(Window.MaxHeightProperty, new Binding("MaxHeight") { Source = MyViewModel });
this.SetBinding(Window.MinWidthProperty, new Binding("MinWidth") { Source = MyViewModel });
this.SetBinding(Window.MinHeightProperty, new Binding("MinHeight") { Source = MyViewModel });

奇怪的是它只能在代码中工作,而不能在 XAML 中工作。更奇怪的是,它默认为 mMin 和 Max 尺寸绑定 TwoWay,但不为您必须指定 « Mode=BindingMode.TwoWay » 的普通尺寸绑定。

微软必须纠正这个错误......


5
投票

此外,您可以将

SizeToContent="WidthAndHeight"
MinHeight
MinWidth
一起使用,因此无需额外致电
MaxHeight
MaxWidth


2
投票

我已经使用下面的代码解决了这个问题。我希望它可以帮助别人。

要点: WPF 中的动态绑定始终仅适用于属性,但不适用于变量。

在 .xaml.cs 文件中声明一个全局公共属性,如下所示:

public Double DynamicHeight { get; set; }

// Set DynamicHeight property value in Window_Loaded or any other event
private void Window_Loaded(object sender, RoutedEventArgs e)
{
     DynamicHeight = 200;
}

在 .xaml 文件中设置动态高度,如下所示:

<Grid Height="{Binding DynamicHeight, Mode=TwoWay}">
</Grid>

如果您觉得这个答案有用,请投票。谢谢!


1
投票

绑定到 MinWidth 和 MinHeight 是正确的。另外,如果您的动态会放大或缩小窗口的大小,则需要绑定到 MaxWidth 和 MaxHeight。


1
投票

我不确定你的具体实现,但我只是写了一个可能有用的例子。

XAML

<Window x:Name="MainWindow"
    x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" 
    MinWidth="200"
    MinHeight="100"
    Width="{Binding ElementName=MainWindow, Path=WindowWidth}"
    Height="{Binding ElementName=MainWindow, Path=WindowHeight}">
    <Grid>
        <Slider 
            x:Name="slWidth" 
            Value="{Binding ElementName=MainWindow, Path=WindowWidth, Mode=TwoWay}"
            Minimum="200"
            Maximum="1600"
            Height="23" HorizontalAlignment="Left" Margin="56,22,0,0" VerticalAlignment="Top" Width="61" />
        <Label 
            Content="Width" 
            Height="28" 
            HorizontalAlignment="Left" 
            Margin="12,22,0,0" 
            Name="Label1" 
            VerticalAlignment="Top" />
        <Slider 
            x:Name="slHeight" 
            Value="{Binding ElementName=MainWindow, Path=WindowHeight, Mode=TwoWay}"
            Minimum="100"
            Maximum="800"
            Height="23" HorizontalAlignment="Left"  VerticalAlignment="Top" Width="61" Margin="56,51,0,0" />
        <Label 
            Content="Height" 
            Height="28" 
            HorizontalAlignment="Left"              
            VerticalAlignment="Top" Margin="12,46,0,0" />
    </Grid>
</Window>

代码

Class MainWindow

    Public Shared ReadOnly WindowWidthProperty As DependencyProperty = _
                           DependencyProperty.Register("WindowWidth", _
                           GetType(Integer), GetType(MainWindow), _
                           New FrameworkPropertyMetadata(Nothing))

    Public Shared ReadOnly WindowHeightProperty As DependencyProperty = _
                         DependencyProperty.Register("WindowHeight", _
                         GetType(Integer), GetType(MainWindow), _
                         New FrameworkPropertyMetadata(Nothing))

    Public Property WindowWidth As Integer
        Get
            Return CInt(GetValue(WindowWidthProperty))
        End Get
        Set(ByVal value As Integer)
            SetValue(WindowWidthProperty, value)
        End Set
    End Property

    Public Property WindowHeight As Integer
        Get
            Return CInt(GetValue(WindowHeightProperty))
        End Get
        Set(ByVal value As Integer)
            SetValue(WindowHeightProperty, value)
        End Set
    End Property


End Class

C# 代码

public readonly DependencyProperty WindowWidthProperty = DependencyProperty.Register("WindowWidth", typeof(Double), typeof(MainWindow), new FrameworkPropertyMetadata());
public readonly DependencyProperty WindowHeightProperty = DependencyProperty.Register("WindowHeight", typeof(Double), typeof(MainWindow), new FrameworkPropertyMetadata());

public double WindowWidth {
    get { return Convert.ToDouble(this.GetValue(WindowWidthProperty)); }
    set { this.SetValue(WindowWidthProperty, value); }
}

public double WindowHeight {
    get { return Convert.ToDouble(this.GetValue(WindowHeightProperty)); }
    set { this.SetValue(WindowHeightProperty, value); }
}

0
投票
Height="{DynamicResource {x:Static SystemParameters.PrimaryScreenHeightKey}}" Width="{DynamicResource {x:Static SystemParameters.PrimaryScreenWidthKey}}"

在我这边工作得很好。


0
投票

我在同时更改窗口高度和宽度时遇到同样的问题。我将视图中的

Height
Width
绑定到视图模型中的
WinHeight
WinWidth

Height="{Binding Path=WinHeight, Mode=TwoWay}"
Width="{Binding Path=WinWidth, Mode=TwoWay}"

并在视图模型中提高

PropertyChangedEvent
,例如:

WinHeight = 600; // some change to WinHeight
WinWidth = 800; // some change to WinWidth
OnPropertyChanged(nameof(WinHeight));
OnPropertyChanged(nameof(WinWidth));

问题是,在经过一些修改后,在视图模型中的

PropertyChangedEvent
上提高
WinHeight
时,它确实会更改视图中的
Height
,但同时 View 将旧的 Width
 值写回 
WinWidth
 。因此,另一个解决方案是分别更改视图模型的 
WinHeight
WinWidth

WinHeight = 600; OnPropertyChanged(nameof(WinHeight)); // this will cause WinWidth be set to current window's Width due to TwoWay binding WinWidth = 800; OnPropertyChanged(nameof(WinWidth));
    

-1
投票
只需添加模式 = TwoWay 宽度=“{绑定窗口宽度,UpdateSourceTrigger=PropertyChanged,模式=双向,FallbackValue=350}”

© www.soinside.com 2019 - 2024. All rights reserved.