如何在 ListBox WPF MVVM 模型中基于 SelectedItem 隐藏和显示 UserControls

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19703655/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 09:59:14  来源:igfitidea点击:

How to hide and show UserControls based on SelectedItem in ListBox WPF MVVM Model

c#wpfmvvmbindinglistbox

提问by user2889489

I have 3 UserControls in my MainWindow,In my UserControl1 i have a ListBox with some names.The UserControl2 and 3 are not visible when we start the application.

我的主窗口中有 3 个用户控件,在我的用户控件 1 中,我有一个带有一些名称的列表框。当我们启动应用程序时,用户控件 2 和 3 不可见。

When i select some name in the listbox of usercontrol1 then the usercontrol2 should appear on my mainwindow,when i select other name then usercontrol3 should appear on my mainwindow.Struggling with this please help me,i'm new to this

当我在 usercontrol1 的列表框中选择某个名称时,usercontrol2 应出现在我的主窗口上,当我选择其他名称时,usercontrol3 应出现在我的主窗口上。遇到这个问题请帮助我,我是新手

This is my UserControlXaml code

这是我的 UserControlXaml 代码

<UserControl x:Class="Wpf_MVVM.UserControl1"
         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" 
         mc:Ignorable="d" 
         x:Name="uc1" Height="Auto" Width="Auto">
<Grid>
    <ListBox Name="listbox" ItemsSource="{Binding mylist}"  HorizontalAlignment="Left" Height="310" VerticalAlignment="Top" Width="150" Margin="0,40,0,0" FontSize="15">

    </ListBox>
    <Label Content="Conversations" HorizontalAlignment="Left" VerticalAlignment="Top"  Height="40" Width="150" FontSize="20" Background="SkyBlue"/>
    <Button Content="Create New Chat" Height="30" HorizontalAlignment="Left" Margin="0,350,0,0" VerticalAlignment="Top" Width="150"/>

</Grid>
</UserControl>

This is my .cs code

这是我的 .cs 代码

public partial class UserControl1 : UserControl
{
    User1 User1 = new User1();
    public UserControl1()
    {
        InitializeComponent();
        this.DataContext = User1;
    }
}
public class User1
{
    private ObservableCollection<string> _mylist = new ObservableCollection<string>();

    public ObservableCollection<string> mylist { get { return _mylist; } }

    public User1()
    {
        mylist.Add("Name1");
        mylist.Add("Name2");
        mylist.Add("Name3");
        mylist.Add("Name4");

    }

This is my mainwindow.xaml code

这是我的 mainwindow.xaml 代码

<Window x:Class="Wpf_MVVM.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:Wpf_MVVM" 
    Title="MainWindow" Background="SlateGray" Height="420" Width="550" >
<Window.Resources>
    <BooleanToVisibilityConverter x:Key="VisibilityConverter" />
</Window.Resources>

<Grid>

    <local:UserControl1 x:Name="uc1"   HorizontalAlignment="Left" VerticalAlignment="Top"/>
    <StackPanel>

        <local:UserControl2 x:Name="uc2"  Visibility="{Binding SelectedItem, Converter={StaticResource VisibilityConverter}}"  HorizontalAlignment="Left" VerticalAlignment="Top" Margin="150,29,0,0" />
        <local:UserControl3 x:Name="uc3" Visibility="{Binding SelectedItem1, Converter={StaticResource VisibilityConverter}}" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="340,29,0,0"/>


    </StackPanel>



</Grid>
</Window>

This is my viewmodel code for usercontrol2 and 3

这是我的 usercontrol2 和 3 的视图模型代码

  public class User : INotifyPropertyChanged
    {

        private bool _selectedItem;
        public bool SelectedItem
        {
            get { return _selectedItem; }
            set
            {
                _selectedItem = value;
                PropertyChanged(this, new PropertyChangedEventArgs("SelectedItem"));
            }
        }
        private bool _selectedItem1;
        public bool SelectedItem1
        {
            get { return _selectedItem1; }
            set
            {
                _selectedItem1 = value;
                PropertyChanged(this, new PropertyChangedEventArgs("SelectedItem1"));
            }
        }

        public class BooleanToVisibilityConverter : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            {

                return value == null ? Visibility.Collapsed : Visibility.Visible;
            }

            public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
            {

                return null;
            }

        }
        public event PropertyChangedEventHandler PropertyChanged;
        private void Notify(string propertyName)
        {
            var handler = PropertyChanged;
            if (handler != null)
                handler(this, new PropertyChangedEventArgs(propertyName));
        }

        private readonly ObservableCollection<string> items = new ObservableCollection<string>();
        private string text;
        private readonly ObservableCollection<string> newitems = new ObservableCollection<string>();
        private string newtext;

        public class Command : ICommand
        {
            private readonly Action action;

            public Command(Action action)
            {
                this.action = action;
            }

            public bool CanExecute(object parameter)
            {
                return true;
            }


            public event EventHandler CanExecuteChanged;
            public void Execute(object parameter)
            {
                action();
            }
        }

        private readonly ICommand addCommand;
        private readonly ICommand sendCommand;
        public User()
        {

            addCommand = new Command(() => items.Add(Text));
            sendCommand = new Command(() => newitems.Add(NewText));
        }



        public IEnumerable<string> Items
        {
            get { return items; }
        }

        public IEnumerable<string> NewItems
        {
            get { return newitems; }
        }


        public ICommand AddCommand
        {
            get { return addCommand; }
        }
        public ICommand SendCommand
        {
            get { return sendCommand; }
        }

        public string Text
        {
            get { return text; }
            set
            {
                if (text == value)
                    return;

                text = value;
                Notify("Text");
            }
        }
        public string NewText
        {
            get { return newtext; }
            set
            {
                if (newtext == value)
                    return;

                newtext = value;
                Notify("NewText");
            }
        }
    }
}

回答by Sheridan

If you want to use a BooleanToVisibilityConverter, then you'll need to create some boolproperties in your view model:

如果你想使用 a BooleanToVisibilityConverter,那么你需要bool在你的视图模型中创建一些属性:

public bool IsControl1Visible
{
    get { return isControl1Visible; }
    set { isControl1Visible = value; NotifyPropertyChanged("IsControl1Visible"); }
}

public bool IsControl2Visible
{
    get { return isControl2Visible; }
    set { isControl2Visible = value; NotifyPropertyChanged("IsControl2Visible"); }
}

Then you'll need a SelectedItemproperty:

然后你需要一个SelectedItem属性:

public string SelectedItem
{
    get { return selectedItem; }
    set { selectedItem = value; NotifyPropertyChanged("SelectedItem"); }
}

You'll also need to create a SelectedItem DependencyPropertyin your first UserControland bind that to the ListBox.SelectedItemproperty (I'm assuming that you either know how to or can find out how to create a DependencyProperty):

您还需要SelectedItem DependencyProperty在第一个中创建 aUserControl并将其绑定到ListBox.SelectedItem属性(我假设您知道如何或可以找到如何创建 a DependencyProperty):

In UserControl1:

UserControl1

<ListBox Name="listbox" ItemsSource="{Binding mylist}" 
    SelectedItem="{Binding SelectedItem, RelativeSource={AncestorType={x:Type 
    local:UserControl1}}}" HorizontalAlignment="Left" Height="310" 
    VerticalAlignment="Top" Width="150" Margin="0,40,0,0" FontSize="15" />

Then you can Bindthe UserControl1.SelectedItemproperty (which is internally bound to the ListBox.SelectedItemproperty) to your view model:

然后你可以BindUserControl1.SelectedItem属性(在内部绑定到ListBox.SelectedItem属性)到你的视图模型:

<local:UserControl1 x:Name="uc1" SelectedItem="{Binding SelectedItem}" 
    HorizontalAlignment="Left" VerticalAlignment="Top"/>

Finally, we can update our view model SelectedItemproperty to change the visibility of the other Usercontrols:

最后,我们可以更新我们的视图模型SelectedItem属性来改变其他Usercontrols的可见性:

public string SelectedItem
{
    get { return selectedItem; }
    set 
    {
        selectedItem = value;
        NotifyPropertyChanged("SelectedItem");
        if (selectedItem == "Some value") 
        {
            IsControl1Visible = true;
            IsControl2Visible = false;
        }
        else
        {
            IsControl2Visible = true;
            IsControl1Visible = false;
        }
    }
}

As an alternative to this method, you mayfind my answer to the WPF MVVM navigate viewspost useful.

作为此方法的替代方法,您可能会发现我对WPF MVVM 导航视图帖子的回答很有用。

回答by Aleksey

You can use power of Binding without additional C# code

无需额外的 C# 代码即可使用强大的 Binding

<Grid>
  <local:UserControl1 x:Name="uc1"   HorizontalAlignment="Left" VerticalAlignment="Top"/>
    <StackPanel>
      <local:UserControl2 x:Name="uc2" Visibility="{Binding ElementName=uc1, Path=SelectedItem, Converter={StaticResource VisibilityConverter}}"  HorizontalAlignment="Left" VerticalAlignment="Top" Margin="150,29,0,0" />
      <local:UserControl3 x:Name="uc3" Visibility="{Binding ElementName=uc2, Path=SelectedItem, Converter={StaticResource VisibilityConverter}}" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="340,29,0,0"/>
    </StackPanel>
</Grid>

or with data triggers:

或使用数据触发器:

<Style TargetType="{x:Type Control}" x:Key="VisibilityStyle1">
            <Setter Property="Visibility" Value="Visible" />
            <Style.Triggers>
                <DataTrigger Binding="{Binding SelectedItem, ElementName=uc1}" Value="{x:Null}">
                    <Setter Property="Visibility" Value="Hidden" />
                </DataTrigger>
            </Style.Triggers>
</Style>

<Style TargetType="{x:Type Control}" x:Key="VisibilityStyle2">
            <Setter Property="Visibility" Value="Visible" />
            <Style.Triggers>
                <DataTrigger Binding="{Binding SelectedItem, ElementName=uc2}" Value="{x:Null}">
                    <Setter Property="Visibility" Value="Hidden" />
                </DataTrigger>
            </Style.Triggers>
</Style>

<Grid>
  <local:UserControl1 x:Name="uc1"   HorizontalAlignment="Left" VerticalAlignment="Top"/>
    <StackPanel>
      <local:UserControl2 x:Name="uc2" Style="{DynamicResource VisibilityStyle1}"  HorizontalAlignment="Left" VerticalAlignment="Top" Margin="150,29,0,0" />
      <local:UserControl3 x:Name="uc3" tyle="{DynamicResource VisibilityStyle2}" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="340,29,0,0"/>
    </StackPanel>
</Grid>