使用具有相同布局的动态TabItem实现TabControl

时间:2017-03-15 14:07:22

标签: c# wpf xaml tabcontrol

编辑:

enter image description here

好的,我会试着通过我的程序界面来描述我想要实现的目标。 它是连接到服务器的客户端,用于检索有关正在运行此服务器的特定环境中正在运行的应用程序的一些信息。到目前为止,它仅适用于1台服务器,因此如果已连接,则需要断开连接并重新连接到另一台服务器,以获取有关另一台服务器正在运行的另一台PC的信息。我想要做的是允许创建更多客户端实例连接到其他服务器,以获得有关更多pc的信息。 我的设计理念是通过TabControl扩展我在MainWindow中设计的界面。通过“+”或任何按钮,我想创建另一个Client接口的实例,但我只需要维护以红色突出显示的元素,而以绿色突出显示的元素必须与所有实例共用。

我现在拥有的是一个窗口,我将所有控件放在显示进程和其他一些内容中,TabControl中的所有选项卡必须具有相同的布局和不同的内容,但它们必须共享相同的LogWindow(绿色框)。

我希望我现在能更好地解释它。

P.S TabControl在图像中显示的是来自另一个图像的简单复制粘贴,我还没有实现它。

我已经看过一些关于动态标签控件项目的教程,特别是this one

问题是我没有正确理解如何将我的MainWindow布局移植为其他标签的标准模板。

这是我开发的代码:

MainWindow.xaml

<Window x:Class="Project_Client.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:Project_Client"
    xmlns:helper="clr-namespace:Helper"
    mc:Ignorable="d"
    ResizeMode="CanResizeWithGrip"
    MinHeight="480" MinWidth="640"
    Title="MainWindow" Height="480" Width="640" Closing="Window_Closing" 
    >
<Window.Resources>
    <BitmapImage x:Key="RevealImage" UriSource="./reveal_icon.png"></BitmapImage>
    <BitmapImage x:Key="HideImage" UriSource="./hide_icon.png"></BitmapImage>
</Window.Resources>

<Grid>

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"></ColumnDefinition>
            <ColumnDefinition Width="auto"></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <TextBlock FontWeight="Bold" VerticalAlignment="Top" Width="86" Height="16" Margin="13,76,0,0" HorizontalAlignment="Left">Process List:</TextBlock>

        <Grid Grid.Column="0" Name="mLeftGrid" Margin="0,0,0,183.4" HorizontalAlignment="Stretch">

            <Grid.Resources>
                <DataTemplate x:Key="StrProperty">
                    <TextBlock Text="{Binding Path=Str}"/>
                </DataTemplate>
                <DataTemplate x:Key="ImgProperty">
                    <Image Source="{Binding Path=Image}"  />
                </DataTemplate>
            </Grid.Resources>
            <Grid.RowDefinitions>
                <RowDefinition Height="228*"/>
                <RowDefinition Height="343*"/>
            </Grid.RowDefinitions>
            <Border Grid.RowSpan="2"
        BorderBrush="Cyan"
        BorderThickness="3"
        HorizontalAlignment="Stretch"
        VerticalAlignment="Stretch"/>
            <ProgressBar x:Name="progressBarProcess" Margin="13,66,-3,0" Height="6" VerticalAlignment="Top" HorizontalAlignment="Left" Width="316"/>
            <TextBlock x:Name="progressText" HorizontalAlignment="Stretch" TextWrapping="Wrap" Text="TextBlock" Width="auto" Margin="12,45,-12,0" Height="19" VerticalAlignment="Top"/>

            <Grid Name="mLeftInnerGrid" Margin="9.8,102,10,0" VerticalAlignment="Top" Grid.RowSpan="2" HorizontalAlignment="Stretch" SizeChanged="mLeftInnerGrid_SizeChanged">

                <ListView x:Name="mCurrentApps" HorizontalAlignment="Left" Height="auto" VerticalAlignment="Top" ItemsSource="{Binding Items, Mode=OneWay}" VirtualizingPanel.IsVirtualizing="true" 
     VirtualizingPanel.VirtualizationMode="Recycling" Margin="0,0,-155.2,0" SizeChanged="mCurrentApps_SizeChanged">
                    <ListView.ItemContainerStyle>
                        <Style TargetType="{x:Type ListViewItem}">
                            <Setter Property="Focusable" Value="False"/>
                            <Style.Triggers>
                                <Trigger Property="IsSelected" Value="True" >
                                    <Setter Property="FontWeight" Value="Bold" />
                                    <Setter Property="Foreground" Value="OrangeRed" />
                                </Trigger>
                            </Style.Triggers>
                            <Style.Resources>
                                <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent"/>
                            </Style.Resources>
                        </Style>
                    </ListView.ItemContainerStyle>
                    <ListView.View>
                        <GridView>
                            <GridViewColumn>
                                <GridViewColumn.Header>
                                    <GridViewColumnHeader Tag="App" Click="GridViewColumnHeader_Click_" Width="auto">App</GridViewColumnHeader>
                                </GridViewColumn.Header>
                                <GridViewColumn.CellTemplate>
                                    <DataTemplate>
                                        <StackPanel Orientation="Horizontal" MinWidth="64">
                                            <Image Width="16" Height="16" Source="{Binding Image}" Margin="4,0,16,0" />
                                            <TextBlock Text="{Binding App}" />
                                        </StackPanel>
                                    </DataTemplate>
                                </GridViewColumn.CellTemplate>
                            </GridViewColumn>
                            <GridViewColumn DisplayMemberBinding="{Binding Process}" >
                                <GridViewColumn.Header>
                                    <GridViewColumnHeader Tag="Process" Click="GridViewColumnHeader_Click_" Width="auto">Process</GridViewColumnHeader>
                                </GridViewColumn.Header>
                            </GridViewColumn>
                            <GridViewColumn FrameworkElement.FlowDirection="RightToLeft">
                                <GridViewColumn.CellTemplate>
                                    <DataTemplate>
                                        <TextBlock Text="{Binding ExecutionTimer}" HorizontalAlignment="Right"></TextBlock>
                                    </DataTemplate>
                                </GridViewColumn.CellTemplate>
                                <GridViewColumn.Header >
                                    <GridViewColumnHeader Tag="Timer" Click="GridViewColumnHeader_Click_" HorizontalContentAlignment="Right" >Active Time</GridViewColumnHeader>
                                </GridViewColumn.Header>
                            </GridViewColumn>
                        </GridView>
                    </ListView.View>

                </ListView>

            </Grid>

        </Grid>

        <Grid Grid.Column="1" Name="mRigthGrid" Margin="0,0,-0.4,182.4" HorizontalAlignment="Right">
            <Grid.RenderTransform>
                <TranslateTransform x:Name="mRightGridAnim"></TranslateTransform>
            </Grid.RenderTransform>
            <Border
        BorderBrush="Coral"
        BorderThickness="3"
        HorizontalAlignment="Stretch"
        VerticalAlignment="Stretch"/>
            <TextBlock FontWeight="Bold" Margin="0,76,248,0" HorizontalAlignment="Right" VerticalAlignment="Top" Width="auto" Height="16">Status:</TextBlock>
            <TextBlock x:Name="mAppStatus" Visibility="Visible" Width="auto" Margin="0,76,45,0" Height="16" VerticalAlignment="Top" HorizontalAlignment="Right"/>
            <TextBox x:Name="mKeyPressed" HorizontalAlignment="Right" Margin="0,98,28,149" TextWrapping="Wrap" Text="..." Width="247" Loaded="keyPressed_Loaded" FontSize="20" IsReadOnly="True"/>
            <Button x:Name="mRecordingButton" Content="Start recording keys" Margin="0,0,77,98" Click="button_Click" HorizontalAlignment="Right" Width="139" Height="19" VerticalAlignment="Bottom"/>
            <TextBlock x:Name="PcName" Margin="8,45,229,0" TextWrapping="Wrap" Text="PC-??????" HorizontalAlignment="Right" Width="57" Height="15" VerticalAlignment="Top" />
            <TextBlock x:Name="numberOfProcesses" HorizontalAlignment="Right" Margin="0,45,132,0" TextWrapping="Wrap" Text="Processes: ???" Height="16" VerticalAlignment="Top"/>

                    </Grid>

    </Grid>

    <DockPanel x:Name="mRevealButton" PreviewMouseLeftButtonUp="mRevealButton_PreviewMouseLeftButtonUp" Margin="0,97,-0.4,183.4" HorizontalAlignment="Right" Width="10">
        <DockPanel.Style>
            <Style TargetType="{x:Type DockPanel}">
                <Style.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter Property="Background" Value="LightGray"/>
                        <Setter Property="ToolTip" Value="Click to show/hide keys input box"/>
                    </Trigger>

                </Style.Triggers>
            </Style>
        </DockPanel.Style>
        <Image x:Name="mRevealImage" Width="16" Source="reveal_icon.png" HorizontalAlignment="Center" VerticalAlignment="Center" />
    </DockPanel>
    <Rectangle x:Name="Background" Visibility="Hidden">
        <Rectangle.Fill>
            <SolidColorBrush Color="{DynamicResource {x:Static SystemColors.InactiveCaptionColorKey}}"/>
        </Rectangle.Fill>
    </Rectangle>
    <ListBox x:Name="logWindow" ItemsSource="{Binding LogEntry, Mode=OneWay}" Grid.IsSharedSizeScope="True" VirtualizingPanel.IsVirtualizing="true" 
     VirtualizingPanel.VirtualizationMode="Recycling" Margin="10,0,8.6,41.4" Height="134" VerticalAlignment="Bottom" >
        <ListBox.ItemContainerStyle>
            <Style TargetType="{x:Type ListBoxItem}" >
                <Setter Property="FontStyle" Value="Italic"></Setter>
                <Style.Triggers>
                    <DataTrigger Binding="{Binding Path=IsError, UpdateSourceTrigger=PropertyChanged}" Value="true">
                        <Setter Property="Foreground" Value="Red"></Setter>

                    </DataTrigger>
                    <DataTrigger Binding="{Binding Path=IsWarning, UpdateSourceTrigger=PropertyChanged}" Value="true">
                    </DataTrigger>

                </Style.Triggers>
                <Style.Resources>
                    <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent"/>

                </Style.Resources>
            </Style>
        </ListBox.ItemContainerStyle>
        <ListBox.ItemTemplate>
            <DataTemplate>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="auto" SharedSizeGroup="Icon" />
                        <ColumnDefinition Width="auto" MinWidth="64" SharedSizeGroup="Log" />
                    </Grid.ColumnDefinitions>
                    <Image Grid.Column="0"  Source="{Binding Path = Img}" Width="16" Height="16"/>
                    <TextBlock Grid.Column="1" Text="{Binding Path = log}" Margin="4,0,0,0" TextTrimming="CharacterEllipsis" HorizontalAlignment="Stretch" />
                </Grid>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
    <Image x:Name="noConnectionImage" Source="no_connection.png" Width="256" Height="256" HorizontalAlignment="Center" VerticalAlignment="Center" Opacity="0.6" Visibility="Hidden" Margin="194,19,183.6,175.4" />
    <TextBlock x:Name="mBlockServerName" VerticalAlignment="Bottom" HorizontalAlignment="Left" Margin="10,0,0,10.4" TextWrapping="Wrap" Text="Server:" Grid.Row="1" />
    <TextBox x:Name="mBoxServerName" VerticalAlignment="Bottom" HorizontalAlignment="Left" Margin="69,0,0,10.4" TextWrapping="Wrap" Text="" Width="123" Grid.Row="1"  />
    <TextBlock x:Name="mBlockServerPort" VerticalAlignment="Bottom" HorizontalAlignment="Left" Margin="210,0,0,10.4" TextWrapping="Wrap" Text="Port:" Grid.Row="1"/>
    <TextBox x:Name="mBoxServerPort" VerticalAlignment="Bottom" HorizontalAlignment="Left" Margin="251,0,0,10.4" TextWrapping="Wrap" Text="" Width="47" Grid.Row="1" />
    <Button x:Name="mButtonConnect" VerticalAlignment="Bottom" HorizontalAlignment="Right" Content="Connect"  Margin="0,0,104.6,10.4" Width="76" Click="mButtonConnect_Click" Grid.Row="1"/>
    <Button x:Name="mButtonDisconnect" VerticalAlignment="Bottom" HorizontalAlignment="Right" Content="Disconnect"  Margin="0,0,9.6,10.4"  Width="75" Grid.Row="1" Click="mButtonDisconnect_Click"/>
</Grid>

MainWindow.cs (只有对填充视图有用的方法)

    public ObservableCollection<ProcessData> Items { get; set; }
    public ObservableCollection<LogItem> LogEntry { get; set; }
    public static MainWindow myInstance;
    private LogItem log;
    private Client client;
    ProcessData indexFocused;
    List<ProcessData> lop = new List<ProcessData>();
    public String serverIp;
    public long port;


    public MainWindow()
    {
        InitializeComponent();  
        myInstance = this;
        InitializeUI();
        attachLogSource();
        this.DataContext = this;
    }

    public void InitializeUI()
    {

        mButtonConnect.IsEnabled = true;
        mAppStatus.Text = "Disconnected.";
        noConnectionImage.Visibility = Visibility.Visible;
        Background.Visibility = Visibility.Visible;
        //mCurrentApps.Visibility = Visibility.Hidden;
        //Items = new ObservableCollection<ProcessData>();
        noConnectionImage.Visibility = Visibility.Visible;
        Background.Visibility = Visibility.Visible;
        noConnectionImage.Source = new BitmapImage(new Uri(thisPath +  "no_connection.png"));
        progressBarProcess.Visibility = Visibility.Hidden;
        progressText.Visibility = Visibility.Hidden;
        //PcName.Visibility = Visibility.Hidden;
       // numberOfProcesses.Visibility = Visibility.Hidden;
        mBoxServerName.Text = "127.0.0.1";
        mBoxServerPort.Text = "11000";
        mButtonDisconnect.IsEnabled = false;
        //mCurrentApps.Visibility = Visibility.Hidden;
        mRecordingButton.IsEnabled = true;
        mRevealButton.Visibility = Visibility.Visible;
        mRevealImage.Source = new BitmapImage(new Uri(thisPath + "hide_icon.png"));
        GridViewColumnResizeBehaviour b = new GridViewColumnResizeBehaviour();
        b.Attach(mCurrentApps);





    }



    private void mButtonConnect_Click(object sender, RoutedEventArgs e)
    {

        client = new Client();
        attachListSource();

        if (!(mBoxServerName.Text.Trim() == String.Empty && mBoxServerPort.Text.Trim() == String.Empty))
        {
            Items.Clear();
            log = new LogItem();
            log.log = "Connecting...";
            LogMessage(log);
            //mCurrentApps.Visibility = Visibility.Hidden;
            mRecordingButton.IsEnabled = false;
            client.wr_monitor();

        }
        else
        {

            log.log = "Must insert a valid address and port.";
            LogMessage(log);
        }
            //MessageBox.Show("Must insert a valid server address and port", "Error", MessageBoxButton.OK, MessageBoxImage.Exclamation);

    }

    private void attachListSource()
    {
        Items = new ObservableCollection<ProcessData>();
        mCurrentApps.ItemsSource = Items;
        Items.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(takeFocus);
    }

    private void attachLogSource()
    {
        if(LogEntry == null)
        {
            LogEntry = new ObservableCollection<LogItem>();
            logWindow.ItemsSource = LogEntry;
            LogEntry.CollectionChanged += (s, e) =>
            {
                if (e.Action ==
                    System.Collections.Specialized.NotifyCollectionChangedAction.Add)
                {
                    logWindow.ScrollIntoView(logWindow.Items[logWindow.Items.Count - 1]);
                }
            };
        }

    } 
    private void updateList()
    {

        var l = lop.OrderBy(o => o.App);
        this.Dispatcher.Invoke(new Action(() =>
        {
            mCurrentApps.Visibility = Visibility.Visible;
            mCurrentApps.ItemsSource = l;
            progressText.Text = "Complete! (" + lop.Count + ")/(" + lop.Count + ")";
            numberOfProcesses.Text = "Processes: " + Items.Count.ToString();
            log = new LogItem();
            log.log = "Received all the processes (" + lop.Count + ")";
            LogMessage(log);
            mCurrentApps.Items.Refresh();
        }));

    }

     private void mButtonDisconnect_Click(object sender, RoutedEventArgs e)
    {
        Client.EndConnect();
        mButtonConnect.IsEnabled = true;

    }

    private void LogMessage(LogItem l)
    {
        l.Img = SystemIcons.Information.ToImageSource() as BitmapSource;
        Application.Current.Dispatcher.Invoke(() =>
        {
            LogEntry.Add(l);
        });
    }

    private void GridViewColumnHeader_Click_(object sender, RoutedEventArgs e)
    {
        ListViewColumnOptions.GridViewColumnHeader_Click_(sender, e);
    }
    private void mRevealButton_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        DockPanelOptions.PerformClickAction(sender, e);
    }

    private void mCurrentApps_SizeChanged(object sender, SizeChangedEventArgs e)
    {
        ListViewColumnOptions.ListView_SizeChanged(sender, e);
    }

    private void mLeftInnerGrid_SizeChanged(object sender, SizeChangedEventArgs e)
    {
            mCurrentApps.Width = mLeftInnerGrid.ActualWidth;   
    }

特别是我想在标签之间只分享视图之间通用的列表框部分(logWindow),但我想用不同的数据填充每个标签。

根据我的理解,我需要创建一个userControl,并在每个将要创建的选项卡中将其实现为数据模板,但我不知道如何实现它而不参考预先构建的示例。

先谢谢。

1 个答案:

答案 0 :(得分:0)

你可以通过简单的数据绑定来实现(这个想法只是因为问题有点模糊):

android:theme="@*android:style/Theme.NoTitleBar"

(以下代码使用nuget包Fody.PropertyChanged和ICommand的标准实现)

android:theme="@android:style/Theme.NoTitleBar"

修改 我用MVVM的基本实现更新了代码