2010-04-20 19 views
17

Tengo algunos problemas cuando intento vincular el alto y el ancho de una ventana a las propiedades en mi modelo de vista. Aquí hay una pequeña aplicación de muestra para ilustrar el problema. Este es el código en app.xaml.xsProblemas con el enlace a la altura y el ancho de la ventana

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

Ésta es 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> 

Y este es el modelo de vista:

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

cuando se inicia el programa de la se llaman a los captadores de WindowHeight y WindowBorderThickness (pero no WindowWidth), por lo que la altura y el borde de la ventana se establece correctamente, pero no el ancho.

Luego agregar el botón que activará PropertyChanged para todas las propiedades, por lo que el modelo de vista ahora se ve así:

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

Ahora, cuando haga clic en el botón, el captador de WindowBorderThickness se llama, pero no los de WindowWidth y WindowHeight. Todo parece muy extraño e inconsistente para mí. ¿Qué me estoy perdiendo?

+1

¿tiene alguna advertencia en la ventana de salida durante la depuración? – Drake

+0

No, no hay advertencias. –

Respuesta

8

voy a tratar de responder a mi propia pregunta. Las vinculaciones funcionan, pero no podemos estar seguros de que el sistema de diseño pida, p. la propiedad Ancho de la ventana.

De MSDN:

Si este elemento es un elemento secundario dentro de algún otro elemento, a continuación, establecer esta propiedad en un valor es realmente sólo un valor sugerido. El sistema de disposición, así como la lógica de disposición particular del elemento padre usarán el valor como una entrada no vinculante durante el proceso de disposición. En términos prácticos, un FrameworkElement es casi siempre el elemento secundario de otra cosa; incluso cuando configura la altura en la ventana. (Para Ventana, ese valor se utiliza cuando el modelo de aplicación subyacente establece los supuestos de representación básicos que crean la Hwnd que aloja la aplicación.)

Una solución que parece funcionar es para obligar a la propiedad WindowWidth a MinWidth y MaxWidth , así como Ancho. Uno de estos será recuperado, al menos en el escenario de prueba que estaba usando anteriormente.

-1

no creo que se puede ajustar el tamaño de la ventana de forma dinámica

0

No estoy seguro acerca de su implementación específica, pero solo escribo un ejemplo que quizás podría ser útil.

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> 

Código

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# Código

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); } 
} 
+1

La diferencia básica aquí es que usted se está vinculando a MainWindow, mientras que yo estoy vinculando a un modelo de vista separado. Esto parece hacer una diferencia, por alguna razón. Si implemento sus controles deslizantes contra mi modelo de vista, no funcionará (a menos que también se vincule a MinHeight y MaxHeight como dije en mi propia respuesta). Gracias por el ejemplo de todos modos. –

1

La unión a MinWidth y MinHeight es correcta. Además, si necesita vincularse a MaxWidth y MaxHeight, si su dinámica ampliará o reducirá el tamaño de la ventana.

4

Además se puede utilizar con el SizeToContent="WidthAndHeight"MinHeight y MinWidth, así que no llamada adicional se requeriría para la MaxHeight y MaxWidth.

9

Tuve el mismo problema y noté que depende de si la altura o el ancho se escriben primero en xaml. Si la altura es primero, entonces el encuadernado solo funciona para él y viceversa. La solución consistió en establecer el modo de encuadernación a 'TwoWay': El proyecto que he hecho fue con EM Studio 2010 y .NET 4.0

27

Intente utilizar dos vías de unión, que trabajó para mí:

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

OK,

Tuve el mismo problema y no pude vincular correctamente las dimensiones de la ventana (mínimo, máximo, normal) a mi modelo de vista a través de XAML.

No sé por qué, pero puedes obtener todas esas vinculaciones sin ningún problema si las haces por código en lugar de hacerlo por XAML.

Aquí está mi código C# que trabajaba:

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

Es extraño que sólo funciona en el código y no en XAML. Es aún más extraño que enlaza TwoWay de forma predeterminada para dimensiones mínimas y máximas, pero no para dimensiones normales para las que debe especificar «Modo = Modoenlazado.TwoWay».

debe haber un error que Microsoft tiene que corregir esto ...

Cuestiones relacionadas