Проблемы с привязкой к высоте и ширине окна - PullRequest
23 голосов
/ 20 апреля 2010

У меня возникают некоторые проблемы, когда я пытаюсь привязать высоту и ширину окна к свойствам в моей модели вида. Вот небольшой пример приложения, чтобы проиллюстрировать проблему. Это код в 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), поэтому высота и граница окна устанавливаются правильно, но не ширина.

Затем я добавляю кнопку, которая будет запускать 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, но не методы WindowWidth и WindowHeight. Все это кажется мне очень странным и непоследовательным. Чего мне не хватает?

Ответы [ 7 ]

38 голосов
/ 09 июня 2013

Попробуйте использовать двухстороннее связывание, у меня это сработало:

Width="{Binding Path=xExt, Mode=TwoWay}"
10 голосов
/ 05 апреля 2013

У меня была такая же проблема, и я заметил, что это зависит от того, будет ли высота или ширина записываться в xaml. Если высота первая, то привязка работает только для нее и наоборот. Решением было установить режим привязки 'TwoWay': Проект, который я сделал, был с MS Studio 2010 и .NET 4.0

9 голосов
/ 20 апреля 2010

Я постараюсь ответить на свой вопрос. Привязки работают, но мы не можем быть уверены, что система макетов запрашивает, например, свойство Width окна.

С MSDN :

Если этот элемент является дочерним элементом в каком-либо другом элементе, то установка этого свойства в значение на самом деле является только рекомендуемым значением. Система компоновки, а также конкретная логика компоновки родительского элемента будут использовать значение в качестве необязательного ввода в процессе компоновки. В практическом плане FrameworkElement почти всегда является дочерним элементом чего-то другого; даже когда вы устанавливаете высоту в окне. (Для Window это значение используется, когда базовая модель приложения устанавливает основные допущения рендеринга, которые создают Hwnd, в котором размещается приложение.)

Решение, которое, кажется, работает, состоит в том, чтобы связать свойство WindowWidth с MinWidth и MaxWidth, а также с Width. Один из них будет найден, по крайней мере, в тестовом сценарии, который я использовал выше.

5 голосов
/ 26 сентября 2012

Кроме того, вы можете использовать SizeToContent="WidthAndHeight" с MinHeight и MinWidth, поэтому для MaxHeight и MaxWidth.

не потребуется дополнительный вызов.
3 голосов
/ 22 ноября 2013

ОК,

У меня была та же проблема, и я не смог правильно привязать размеры окна (мин., Макс., Нормаль) к моей модели вида через 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.Еще более странно, что он привязывает TwoWay по умолчанию для измерений mMin и Max, но не для нормальных измерений, для которых необходимо указать «Mode = BindingMode.TwoWay».

Должна быть ошибка, которую должна иметь Microsoftправильно об этом ...

1 голос
/ 24 марта 2011

Привязка к MinWidth и MinHeight верна. Кроме того, если вам нужно привязать к MaxWidth и MaxHeight, если ваша динамика будет увеличивать или уменьшать размер окна.

0 голосов
/ 20 апреля 2010

Я не уверен в вашей конкретной реализации, но я просто напишу пример, который может быть полезным.

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); }
}
...