在WPF中添加/删除Canvas上的用户控件

时间:2012-03-16 10:21:23

标签: wpf canvas user-controls

我创建了两个具有多个文本框,组合框和按钮的WPF用户控件。在主wpf窗口中,我创建了一个Canvas和一个包含两个列表项的列表框。我的要求是,如果选择第一个列表框项,第一个用户控件应该添加到画布。如果我选择第二个列表框项,则先前添加的用户控件应该隐藏,第二个应该添加/显示。任何人都可以为此代码提供示例吗?

下面是我写的代码。我创建了两个用户控件。

UserControl1.xaml

    <UserControl x:Class="UserControl1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="210" Height="210" x:Name="UCntl1">
    <Grid>
        <StackPanel>
        <GroupBox Header="Text Boxes">
            <StackPanel Orientation="Horizontal">
                <StackPanel>
                    <Label Margin="4" Height="21">TextBox1</Label>
                    <Label Margin="4" Height="21">TextBox2</Label>
                    <Label Margin="4" Height="21">TextBox3</Label>
                </StackPanel>
                <StackPanel>
                    <TextBox Width="100" Height="21" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="4">0.1</TextBox>
                    <TextBox Width="100" Height="21" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="4">0.2</TextBox>
                    <TextBox Width="100" Height="21" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="4">0.3</TextBox>
                </StackPanel>
            </StackPanel>
        </GroupBox>
            <GroupBox Header="Conbo Boxes">
                <StackPanel Orientation="Horizontal">
                    <StackPanel>
                        <Label Margin="4" Height="21">ComboBox1</Label>
                        <Label Margin="4" Height="21">ComboBox2</Label>
                        <Label Margin="4" Height="21">ComboBox3</Label>
                    </StackPanel>
                    <StackPanel>
                        <ComboBox Width="100" Height="21" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="4">
                            <ComboBoxItem>Item AAA</ComboBoxItem>
                        </ComboBox>
                        <ComboBox Width="100" Height="21" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="4">
                            <ComboBoxItem>Item BBB</ComboBoxItem>
                        </ComboBox>
                        <ComboBox Width="100" Height="21" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="4">
                            <ComboBoxItem>Item CCC</ComboBoxItem>
                        </ComboBox>
                    </StackPanel>
                </StackPanel>
            </GroupBox>
        </StackPanel>
    </Grid>
</UserControl>

UserControl2.xaml

<UserControl x:Class="UserControl2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="210" Height="210" x:Name="UCntl2">
<Grid>
    <StackPanel>
        <GroupBox Header="Conbo Boxes">
            <StackPanel Orientation="Horizontal">
                <StackPanel>
                    <Label Margin="4" Height="21">ComboBox1</Label>
                    <Label Margin="4" Height="21">ComboBox2</Label>
                    <Label Margin="4" Height="21">ComboBox3</Label>
                </StackPanel>
                <StackPanel>
                    <ComboBox Width="100" Height="21" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="4"></ComboBox>
                    <ComboBox Width="100" Height="21" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="4"></ComboBox>
                    <ComboBox Width="100" Height="21" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="4"></ComboBox>
                </StackPanel>
            </StackPanel>
        </GroupBox>
        <GroupBox Header="Text Boxes">
            <StackPanel Orientation="Horizontal">
                <StackPanel>
                    <Label Margin="4" Height="21">TextBox1</Label>
                    <Label Margin="4" Height="21">TextBox2</Label>
                    <Label Margin="4" Height="21">TextBox3</Label>
                </StackPanel>
                <StackPanel>
                    <TextBox Width="100" Height="21" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="4"></TextBox>
                    <TextBox Width="100" Height="21" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="4"></TextBox>
                    <TextBox Width="100" Height="21" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="4"></TextBox>
                </StackPanel>
            </StackPanel>
        </GroupBox>
    </StackPanel>
</Grid>

Window1.xaml

<Window x:Class="Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="Auto" Width="Auto">
<Grid>
    <StackPanel Orientation="Horizontal">
        <Grid Margin="0,0,0,0" Width="Auto" Height="Auto" VerticalAlignment="Top">
            <ListBox Margin="0,0,0,0" HorizontalAlignment="Left" Width="Auto" Height="Auto" VerticalAlignment="Top" BorderBrush="White">
                <ListBoxItem Name="LstItem1" Selected="LstItem1_Selected">User Control 1</ListBoxItem>
                <ListBoxItem Name="LstItem2" Selected="LstItem2_Selected">User Control 2</ListBoxItem>
            </ListBox>
        </Grid>
        <Grid Width="10" Background="LightGray"></Grid>
        <Grid Margin="0,0,0,0">
            <Canvas Name="Canvas1" Width="210" Height="210" VerticalAlignment="Top">

            </Canvas>
        </Grid>

    </StackPanel>
</Grid>

Widow1.xaml.vb

Class Window1 

Private Sub LstItem1_Selected(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
    Canvas1.Children.Clear()
    Canvas1.Children.Add(New UserControl1)
End Sub

Private Sub LstItem2_Selected(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
    Canvas1.Children.Clear()
    Canvas1.Children.Add(New UserControl2)
End Sub

结束班

问题

我在删除画布中的先前控件后添加了用户控件。因此,在将控件重新添加到画布时,UserControls列表框中的选定值将被清除。是否有任何方法可以在画布上隐藏用户控件,而不是从画布中删除控件。

2 个答案:

答案 0 :(得分:1)

这应该让你开始。这并不是我在一个真实的项目中如何做到这一点,但足够接近。我希望有一种简单的方法可以将项目附加到本网站的答案中。

最终结果如下:

enter image description here enter image description here

<强>的App.xaml

<Application x:Class="SO9735486.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:vm="clr-namespace:SO9735486.ViewModels"
             xmlns:v="clr-namespace:SO9735486.Views"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <DataTemplate DataType="{x:Type vm:MainViewModel}">
            <v:MainView/>
        </DataTemplate>
        <DataTemplate DataType="{x:Type vm:FirstContentViewModel}">
            <v:FirstContentView/>
        </DataTemplate>
        <DataTemplate DataType="{x:Type vm:SecondContentViewModel}">
            <v:SecondContentView/>
        </DataTemplate>
    </Application.Resources>
</Application>

<强> MainWindow.xaml

<Window x:Class="SO9735486.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow">
</Window>

<强> MainWindow.xaml.cs

namespace SO9735486
{
    using System.Windows;
    using SO9735486.ViewModels;

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            this.Content = new MainViewModel();
        }
    }
}

<强> ViewModel.cs

namespace SO9735486.ViewModels
{
    using System;
    using System.ComponentModel;
    using System.Windows;
    using System.Windows.Threading;

    // http://kentb.blogspot.com/2009/04/mvvm-infrastructure-viewmodel.html
    public abstract class ViewModel : INotifyPropertyChanged
    {
        private readonly Dispatcher _dispatcher;

        protected ViewModel()
        {
            if (Application.Current != null)
            {
                _dispatcher = Application.Current.Dispatcher;
            }
            else
            {
                //this is useful for unit tests where there is no application running
                _dispatcher = Dispatcher.CurrentDispatcher;
            }

        }

        [field: NonSerialized]
        public event PropertyChangedEventHandler PropertyChanged;

        protected Dispatcher Dispatcher
        {
            get { return _dispatcher; }
        }

        protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
        {
            var handler = this.PropertyChanged;

            if (handler != null)
            {
                handler(this, e);
            }
        }

        protected void OnPropertyChanged(string propertyName)
        {
            OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
        }
    }
}

<强> ContentViewModel.cs

namespace SO9735486.ViewModels
{
    public abstract class ContentViewModel : ViewModel
    {
        private readonly string displayName;

        protected ContentViewModel(string displayName)
        {
            this.displayName = displayName;
        }

        public string DisplayName
        {
            get { return this.displayName; }
        }
    }
}

<强> FirstContentViewModel.cs

namespace SO9735486.ViewModels
{
    public sealed class FirstContentViewModel : ContentViewModel
    {
        private string name;

        public FirstContentViewModel()
            : base("First")
        {
        }

        public string Name
        {
            get { return this.name; }
            set
            {
                if (this.name != value)
                {
                    this.name = value;
                    this.OnPropertyChanged("Name");
                }
            }
        }
    }
}

<强> SecondContentViewModel.cs

namespace SO9735486.ViewModels
{
    public sealed class SecondContentViewModel : ContentViewModel
    {
        public SecondContentViewModel()
            : base("Second")
        {
        }
    }
}

<强> MainViewModel.cs

namespace SO9735486.ViewModels
{
    using System.Collections.Generic;
    using System.Linq;

    public sealed class MainViewModel : ViewModel
    {
        private readonly ICollection<ContentViewModel> contentViewModels;
        private ContentViewModel selectedContentViewModel;

        public MainViewModel()
        {
            this.contentViewModels = new List<ContentViewModel>
            {
                new FirstContentViewModel(),
                new SecondContentViewModel()
            };

            this.selectedContentViewModel = this.contentViewModels.First();
        }

        public ICollection<ContentViewModel> ContentViewModels
        {
            get { return this.contentViewModels; }
        }

        public ContentViewModel SelectedContentViewModel
        {
            get { return this.selectedContentViewModel; }
            set
            {
                if (this.selectedContentViewModel != value)
                {
                    this.selectedContentViewModel = value;
                    this.OnPropertyChanged("SelectedContentViewModel");
                }
            }
        }
    }
}

<强> FirstContentView.xaml

<UserControl x:Class="SO9735486.Views.FirstContentView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <StackPanel>
        <Label>First Content View</Label>
        <TextBox Text="{Binding Name}"/>
    </StackPanel>
</UserControl>

<强> SecondContentView.xaml

<UserControl x:Class="SO9735486.Views.SecondContentView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <StackPanel>
        <Label>Second content view</Label>
        <Rectangle Fill="Blue" Width="100" Height="30"/>
    </StackPanel>
</UserControl>

<强> MainView.xaml

<UserControl x:Class="SO9735486.Views.MainView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <DockPanel>
        <ComboBox DockPanel.Dock="Top" ItemsSource="{Binding ContentViewModels}" SelectedItem="{Binding SelectedContentViewModel}" DisplayMemberPath="DisplayName"/>
        <ContentControl Content="{Binding SelectedContentViewModel}"/>
    </DockPanel>
</UserControl>

答案 1 :(得分:0)

仅对Windows1.xaml.vb所做的更改。代码bhind文件应如下所示。该问题的答案是使用callinf Canvas1.Clear(),将添加的用户控件的可见性设置为Windows.Visibility.Collapsed。

<强> Window1.xaml.vb

Class Window1 
Private U1 As Integer
Private U2 As Integer
Private Sub LstItem1_Selected(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
    Canvas1.Children.Item(U1).Visibility = Windows.Visibility.Visible
    Canvas1.Children.Item(U2).Visibility = Windows.Visibility.Collapsed
End Sub

Private Sub LstItem2_Selected(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
    Canvas1.Children.Item(U2).Visibility = Windows.Visibility.Visible
    Canvas1.Children.Item(U1).Visibility = Windows.Visibility.Collapsed
End Sub

Private Sub Window1_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded
    U1 = Canvas1.Children.Add(New UserControl1)
    U2 = Canvas1.Children.Add(New UserControl2)

    Canvas1.Children.Item(U1).Visibility = Windows.Visibility.Collapsed
    Canvas1.Children.Item(U2).Visibility = Windows.Visibility.Collapsed
End Sub
End Class