gpt4 book ai didi

mvvm - 使用 MVVM 单击按钮时折叠/可见用户控件 - 无交换机制 -

转载 作者:行者123 更新时间:2023-12-03 10:20:14 25 4
gpt4 key购买 nike

在我的场景中,我有一个 MainView + MainViewModel、UserControl1 + UserControl 2。
在 MainView 中,我有 2 个按钮标记为:Button_ShowUserControl1 + Button_ShowUserControl2。
在 MainView 的下部,我有一个“ContentGrid”,它采用/should_take...每个用户控件。

我的目标:

单击 Button_ShowUserControl1 时 用户控制1 可见用户控件2 或任何其他 UserControl 必须设置为 已折叠 .同样适用于 Button_ShowUserControl2。

我的问题:

1.) 由于用户控件应在应用程序启动时加载,我怎样才能将它们全部放在一个“ContentGrid”中?这实际上是不可能的......那么我怎样才能让一个 UserControl 可见而另一个在同一个地方/“ContentGrid”刚刚折叠?

2.) 作为 1.) 似乎不可能我如何在应用程序启动时实例化所有 UserControls 并在单击相应按钮时使它们仅可见/折叠?

3.) 由于 UserControl 有一个属性 Visibility = Visible/Hidden/Collapsed,我怎样才能绑定(bind)到 ViewModel 中的属性返回像 Collapsed 这样的值?我只能得到像 Visibility = false/true 这样的 bool 值?

我的测试代码:

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

是的,代码是错误的,所以我在这里问:)

最佳答案

这段代码只有两件事有问题。

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

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

2)可见性不是 bool 值,它是一个枚举。因此,您需要使用转换器将 bool 值转换为可见性。观察:
<Window ...>
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVis" />
</Window.Resources>

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

应该是这样的。希望这可以帮助。

还有其他一些你留下的线索可能会影响它的工作能力。例如,您没有显示最大的容器元素......您是否将所有内容都包装在 StackPanel 中?例如,如果您将所有内容包装在 Grid 中,则控件将覆盖所有内容。

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

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

您可以做的另一件事是确保您对要显示和隐藏的每个 View 都有一个唯一的 ViewModel:
public class MyFirstViewModel : ViewModel
{

}

public class MySecondViewModel : ViewModel
{

}

然后从您的“父”或“主” View 模型中,您可以通过将 View 模型放在集合中来显示或隐藏所需的 View :
public MyMainViewModel : ViewModel
{
public ObservableCollection<ViewModel> ViewsToShow
{
...
}

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

要将 View 中的所有内容连接起来,您可以使用它们的用户控件对这些类型进行数据模板化(但这不会导致这些 View 被实例化,除非需要它们:
<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>

对于您放入“ViewsToShow”的任何 ViewModel, View 将​​自动在适当的 View 中看到该 View 和模板。同样,无需在需要之前实例化它。

这可能比将所有东西都放在 View 中并设置可见性要干净一些,但这取决于您对每个 View 都有一个唯一的 View 模型类型,但情况可能并非如此。

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

假设您有上一节中的设置,其中包含定义了数据模板的 2 个 View 模型。让我们稍微改变一下 MainViewModel:
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。
<Window ...>
<!-- DataTemplates Here -->
<Button Command="{Binding SwapViewsCommand}">Swap!</Button>
<ContentControl Content="{Binding View}" />
</Window>

就是这样。这里的 secret 是我保存了对原始 View 模型的引用。这样,假设在 View 模型中有一个字符串属性,在 DataTemplated 用户控件中有一个关联的文本框,带有 。双向绑定(bind) 那么状态将基本上被保存。

关于mvvm - 使用 MVVM 单击按钮时折叠/可见用户控件 - 无交换机制 -,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2097253/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com