Collapse / Visible User Controls auf Knopf Klicken Sie mit MVVM - ohne Swap-Mechanismus -

StackOverflow https://stackoverflow.com/questions/2097253

  •  21-09-2019
  •  | 
  •  

Frage

In meinem Szenario habe ich ein Mainview + MainViewModel, UserControl1 + Usercontrol 2. Im Mainview Ich habe 2 Buttons mit der Aufschrift: Button_ShowUserControl1 + Button_ShowUserControl2. Am unteren Teil des Mainview Ich habe eine „ContentGrid“, die / nimmt should_take ... jede Usercontrol.

Mein Ziel:

Wenn Button_ShowUserControl1 geklickt UserControl1 ist Visible und UserControl2 ODER anderes Benutzersteuerelement muss auf Komprimiert . Gleiches gilt für Button_ShowUserControl2.

Mein Problem:

1.) Da die Benutzersteuerelemente werden bei Anwendung geladen werden beginnen, wie kann ich sie alle zusammen in einem „ContentGrid“? Das ist eigentlich nicht möglich ... so wie kann ich ein Benutzersteuerelement sichtbar zu machen, während die andere an der gleichen Stelle ist / „ContentGrid“ gerade zusammengebrochen?

2.) Wie 1.) scheint nicht möglich, wie kann ich alle Benutzersteuerelemente beim Start der Anwendung instanziiert und machen sie nur sichtbar / Komprimiert wenn entsprechende Schaltfläche geklickt wird?

3). Als Usercontrol hat eine Eigenschaft Sichtbarkeit = Visible / versteckte / Komprimiert, wie kann ich binden an eine Eigenschaft in einem Ansichtsmodell zurückkehren solcher Wert wie Komprimiert? Ich konnte nur einen Booleschen Wert wie Sichtbarkeit = false / true?

erhalten

Mein Testcode:

<Grid x:Name="LayoutRoot" Background="#FFBDF5BD" ShowGridLines="False">
    <Grid.RowDefinitions>
        <RowDefinition Height="96*" />
        <RowDefinition Height="289*" />
    </Grid.RowDefinitions>      
    <Grid HorizontalAlignment="Stretch" Name="MenuGrid" VerticalAlignment="Stretch" Background="#FFCECEFF">
        <StackPanel Name="stackPanel1" Background="#FFEDFF00" Orientation="Horizontal">
            <Button Content="User Data 1" Height="35" Name="button1" Command="{Binding  Path=ShowUserControl1Command}" Width="150" Margin="100,0,0,0" />
            <Button Content="User Data 2" Height="35" Name="button2" Width="150" Margin="100,0,0,0" />
        </StackPanel>
    </Grid>
    <Grid Grid.Row="1" HorizontalAlignment="Stretch" Name="ContentGrid" VerticalAlignment="Stretch" Background="#FFB15454" />
</Grid>

<UserControl x:Class="SwapUserControls.MVVM.UserControl2"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:vm="clr-namespace:SwapUserControls.MVVM.ViewModel"
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300" Visibility="{Binding IsUserControl1Collapsed, Path=Value}">

<UserControl.Resources>
    <vm:MainViewModel x:Key="MainViewModelID" />
</UserControl.Resources>

<UserControl.DataContext>
    <Binding Source="{StaticResource MainViewModelID}" />
</UserControl.DataContext>

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="228*" />
        <RowDefinition Height="72*" />
    </Grid.RowDefinitions>
    <Button Content="UserControl2" Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="112,27,0,0" Name="button1" VerticalAlignment="Top" Width="75" />
    <DataGrid HorizontalAlignment="Stretch" Name="dataGrid1" VerticalAlignment="Stretch" Background="#FFC046F8" />
</Grid>

public class MainViewModel : ViewModelBase
{
    RelayCommand _ShowUserControl1Command;
    private bool _IsUserControl1Collapsed;

    public RelayCommand ShowUserControl1Command
    {
        get
        {
            if (_ShowUserControl1Command == null)
            {
                _ShowUserControl1Command = new RelayCommand( () => ShowUserControl1() );                       
            }
            return _ShowUserControl1Command;
        }
    }

    public void ShowUserControl1()
    {
        _IsUserControl1Collapsed = true;
    }

    public bool IsUserControl1Collapsed 
    {          
        get
        {
            return _IsUserControl1Collapsed;
        }  
    }        
}

Ja, der Code ist falsch, deshalb frage ich hier:)

War es hilfreich?

Lösung

Sie haben nur zwei Dinge falsch mit diesem Code.

1) Sie können die Sichtbarkeit einer Usercontrol direkt nicht gesetzt ... Sie haben es auf einen Behälter zu setzen:

<Grid Visibility="Collapsed">
    <myControls:MyUserControl />
</Grid>

2) Die Sicht ist kein boolean Wert, es eine Enumeration ist. Als solche müssen Sie einen Konverter zu konvertieren von boolean Sichtbarkeit verwenden. Beachten Sie:

<Window ...>
<Window.Resources>
     <BooleanToVisibilityConverter x:Key="BoolToVis" />
</Window.Resources>

<Grid Visibility="{Binding ShouldShowUsercontrol1, Converter={StaticResource BoolToVis}}">
     <myControls:MyUserControl />
</Grid>
</Window>

Das sollte es sein. Hoffe, das hilft.

Es gibt andere Dinge, die Sie verlassen Hinweise darauf, dass möglicherweise die Fähigkeit, dies zu Arbeit beeinflussen. Zum Beispiel Sie das größte Containerelement nicht zeigen ... wickeln Sie alles in einem Stackpanel? Wenn Sie alles in einem Gitter wickeln, zum Beispiel, werden die Kontrollen alles in Schichten überlagern.

Versuchen Sie, diese Änderungen, die ich vorschlagen ... es sollte Ihnen näher.


Edit: Eine weitere Idee mit Datenvorlagen

Eine andere Sache, die Sie machen tun könnte, dass Sie haben eine einzigartige Ansichtsmodell für jede dieser Ansichten, die Sie wollen zeigen, und auszublenden:

public class MyFirstViewModel : ViewModel
{

}

public class MySecondViewModel : ViewModel
{

}

Dann aus dem „Eltern“ oder „main“ Ansichtsmodell, Sie zeigen oder verbergen die Ansichten, die Sie aufgrund wollen, dass sie in einer Sammlung von Viewmodels zu haben:

public MyMainViewModel : ViewModel
{
     public ObservableCollection<ViewModel> ViewsToShow
     {
          ...
     }

     public void ShowFirstViewModel()
     {
          ViewsToShow.Add(new MyFirstViewModel());
     }
}

alles, um Draht aus Ihrer Sicht, würden Sie dann Datatemplate diese Typen mit ihren Benutzersteuerungen (dies würde aber nicht Ursache dieser Ansichten instanziiert werden, wenn sie gebraucht wurden:

<Window ...>
     <Window.Resources>
          <DataTemplate DataType="{x:Type myViewModels:MyFirstViewModel}">
               <myViews:MyFirstView />
          </DataTemplate>

          <DataTemplate DataType="{x:Type myViewModels:MySecondViewModel}">
               <myViews:MySecondView />
          </DataTemplate>
     </Window.Resources>

     <ItemsControl ItemsSource="{Binding ViewsToShow}" />

</Window>

Und für alle Viewmodel Sie in „ViewsToShow“ setzen, sieht die Ansicht automatisch, dass und Vorlage in der entsprechenden Ansicht. Wieder ohne es zu instanziieren, bevor es gebraucht wird.

Dies ist wahrscheinlich ein wenig sauberer als alle einzelne Sache in der Ansicht setzen und die Sichtbarkeit einstellen, aber es wäre abhängig von Ihnen einen einzigartigen Blick Modelltyp für jede Ansicht haben, was nicht der Fall sein könnte.


Die Frage Zustand des Sparens kommt auf, wenn der DataTemplated Ansatz. Die Lösung hier ist Ihr Ansichtsmodell als der Zustand der Steuerung zu treten und beide Ihre Viewmodel und Ihre Ansichten entsprechend zu gestalten. Hier ist ein Beispiel, das Sie tauschen Sie Ihre Ansichten mit DataTemplating erlaubt, aber wieder Schalt und her Zustand speichert.

Angenommen, Sie das Setup aus dem letzten Abschnitt w / 2 Viewmodel, die Datatemplates definiert haben. Lassen Sie uns Änderung auf der MainViewModel ein wenig:

public MyMainViewModel : ViewModel
{
     public RelayCommand SwapViewsCommand
     {
          ...
     }

     public ViewModel View
     {
          ...
     }
     private ViewModel _hiddenView;
     public MyMainViewModel()
     {
          View = new MyFirstViewModel();
          _hiddenView = new MySecondViewModel();
          SwapViewsCommand = new RelayCommand(SwapViewModels);
     }

     public void SwapViewModels()
     {
          var hidden = _hiddenView;
          _hiddenView = View;
          View = hidden;
     }
}

Und ein paar Änderungen an der Hauptansicht. Ich habe die Datatemplates der Kürze halber weggelassen.

<Window ...>
     <!-- DataTemplates Here -->
     <Button Command="{Binding SwapViewsCommand}">Swap!</Button>
     <ContentControl Content="{Binding View}" />
</Window>

Das ist es. Das Geheimnis hier ist, dass ich den Verweis auf die ursprüngliche Ansicht Modell zu speichern. Auf diese Weise lassen Sie sich sagt, es gibt eine String-Eigenschaft in einem Viewmodel und ein dazugehöriges Textfeld in dem DataTemplated Usercontrol mit einem Zwei-Wege-Bindung , dann wird der Zustand im Wesentlichen gespeichert werden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top