首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >基于MVVM的ButtonClick上的崩溃/可见ButtonClick-无交换机制-

基于MVVM的ButtonClick上的崩溃/可见ButtonClick-无交换机制-
EN

Stack Overflow用户
提问于 2010-01-19 21:31:17
回答 1查看 9.2K关注 0票数 1

在我的场景中,我有一个MainView + MainViewModel,UserControl1 + UserControl 2,在MainView中有两个标记为Button_ShowUserControl1 + Button_ShowUserControl2的按钮。在MainView的较低部分,我有一个"ContentGrid“,它接受/应该采取.每一个UserControl。

我的目标:

单击Button_ShowUserControl1时,、UserControl1、、可见的UserControl2或任何其他UserControl必须设置为。对于Button_ShowUserControl2也是有效的。

我的问题:

1.)由于UserControls将在应用程序启动时加载,我如何将它们放在一个"ContentGrid“中?这实际上是不可能的。那么,当另一个UserControl在同一个位置/“ContentGrid”刚刚崩溃时,我如何才能使其可见呢?

2.)( 1.)似乎不可能,如何在应用程序开始时实例化所有的UserControls,并在单击相应的Button时才使它们可见/折叠?

3.)由于UserControl具有属性可见性=可见/隐藏/折叠,那么如何绑定到ViewModel中的属性以返回类似折叠的值?我只能得到一个布尔值,比如能见度= false/true?

我的测试代码:

代码语言:javascript
复制
<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>

代码语言:javascript
复制
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;
        }  
    }        
}

是的,代码是错误的,因此我在这里问:)

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2010-01-20 16:26:28

这段代码只有两处错误。

1)不能直接设置用户控件的可见性.您必须在容器上设置它:

代码语言:javascript
复制
<Grid Visibility="Collapsed">
    <myControls:MyUserControl />
</Grid>

2)可见性不是布尔值,而是枚举。因此,您需要使用转换器将布尔值转换为可见性。观察:

代码语言:javascript
复制
<Window ...>
<Window.Resources>
     <BooleanToVisibilityConverter x:Key="BoolToVis" />
</Window.Resources>

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

应该是这样的。希望这能有所帮助。

还有其他的事情,你留下的线索,可能会影响这个工作的能力。例如,您没有显示最大的容器元素..。你是用StackPanel包装所有东西吗?例如,如果要将所有内容包装在网格中,则控件将在层中覆盖所有内容。

试试我建议的改变..。它应该能让你更接近。

编辑:使用数据模板的另一个想法

您可以做的另一件事是确保要显示和隐藏的每个视图都有一个唯一的ViewModel:

代码语言:javascript
复制
public class MyFirstViewModel : ViewModel
{

}

public class MySecondViewModel : ViewModel
{

}

然后,在“父”或“主”ViewModel中,通过在ViewModels集合中显示或隐藏所需的视图:

代码语言:javascript
复制
public MyMainViewModel : ViewModel
{
     public ObservableCollection<ViewModel> ViewsToShow
     {
          ...
     }

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

若要将视图中的所有内容连接起来,则需要将这些类型与其用户控件连接起来(但这不会导致这些视图被实例化,除非它们是需要的:

代码语言:javascript
复制
<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>

对于输入“ViewModels”的任何ViewsToShow,视图将自动在适当的视图中看到该视图和模板。同样,不需要在需要之前实例化它。

这可能比把所有的东西都放在视图中和设置可见性要干净一些,但是它将取决于您对每个视图都有一个唯一的视图模型类型,这可能不是这样的。

在使用DataTemplated方法时,出现了保存状态的问题。这里的解决方案是将ViewModel作为控件的状态,并相应地设计ViewModels和视图。下面是一个允许您使用DataTemplating交换视图的示例,但是切换来回保存状态。

假设您拥有定义了数据板的最后一节w/ 2视图模型中的设置。让我们稍微修改一下MainViewModel:

代码语言:javascript
复制
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;
     }
}

以及对主视图的几处改动。为了简洁起见,我省略了DataTemplates。

代码语言:javascript
复制
<Window ...>
     <!-- DataTemplates Here -->
     <Button Command="{Binding SwapViewsCommand}">Swap!</Button>
     <ContentControl Content="{Binding View}" />
</Window>

就这样。这里的秘诀是我保存了对原始视图模型的引用。这样,假设在视图模型中有一个字符串属性,在DataTemplated用户控件中有一个与双向绑定相关联的textbox,那么状态实际上就会被保存。

票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2097253

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档