0

我有一个异步服务器在本地网络上监听客户端。当每个客户端向服务器发送连接消息时,我希望服务器在表格中显示客户端的名称。

假设我已经将客户端的名称和 IP 地址作为字符串 ClientDetails 用 _ 分隔,例如“PC5_192.168.1.10”

*编辑 *

我想要的是

当客户加入时,我想将每个客户作为新行添加到表/网格中。

我正在使用 WPF。vb.net 或 C# 答案都可以,我可以自己翻译。

4

1 回答 1

3

我准备了一个“WPF方式”的小例子来做到这一点。在我的电脑上看起来像这样:

在此处输入图像描述

我使用随机值作为数据源:

 public class RandomConnectionAdder
    {
        public Timer timer;
        public Random random = new Random();

        public Action<Connection> OnConnectionAdded { get; set; }

        public RandomConnectionAdder(Action<Connection> onConnectionAdded)
        {
            OnConnectionAdded = onConnectionAdded;
            timer = new Timer(x => AddConnection(), null, 5000, 2000);
        }

        private void AddConnection()
        {
            var computernumber = random.Next(1, 50);
            var newrandomconnection = new Connection()
                {
                    ComputerName = "PC" + computernumber.ToString(), 
                    IPAddress = "192.168.1." + computernumber,
                    ConnectionTime = DateTime.Now
                };

            if (OnConnectionAdded != null)
                OnConnectionAdded(newrandomconnection);
        }
    }

请注意,我通过使用委托添加了一个间接级别Action<Connection>来保持关注点的分离。“监听器”负责监听传入的连接,添加新连接时该做什么超出了它的范围。

这是模型类:

  public class Connection: INotifyPropertyChanged
    {
        private string _computerName;
        public string ComputerName
        {
            get { return _computerName; }
            set
            {
                _computerName = value;
                OnPropertyChanged("ComputerName");
            }
        }

        private string _ipAddress;
        public string IPAddress
        {
            get { return _ipAddress; }
            set
            {
                _ipAddress = value;
                OnPropertyChanged("IPAddress");
            }
        }

        private DateTime _connectionTime;
        public DateTime ConnectionTime
        {
            get { return _connectionTime; }
            set
            {
                _connectionTime = value;
                OnPropertyChanged("ConnectionTime");
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }

这是窗口代码隐藏:

 public partial class Window6 : Window
    {
        private RandomConnectionAdder adder;
        private ObservableCollection<Connection> Connections;

        public Window6()
        {
            InitializeComponent();
            Connections = new ObservableCollection<Connection>();
            adder = new RandomConnectionAdder(x => Dispatcher.BeginInvoke((Action) (() => AddConnection(x))));
            DataContext = Connections;
        }

        private void AddConnection(Connection connection)
        {
            Connections.Add(connection);
        }
    }

如您所见,窗口实例化RandomConnectionAdder并将其OnConnectionAdded操作设置为 lambda,该 lambdaObservableCollection通过Dispatcher.

最后,这是整个 XAML:

<Window x:Class="WpfApplication5.Window6"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window6" Height="300" Width="300">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>

        <GroupBox Header="DataGrid">
            <DataGrid ItemsSource="{Binding}" AutoGenerateColumns="False" IsReadOnly="True">
                <DataGrid.Columns>
                    <DataGridTextColumn Header="Computer Name" Binding="{Binding ComputerName}"/>
                    <DataGridTextColumn Header="IP Address" Binding="{Binding IPAddress}"/>
                    <DataGridTextColumn Header="Connection Time" Binding="{Binding ConnectionTime, StringFormat='HH:mm:ss'}"/>
                </DataGrid.Columns>
            </DataGrid>
        </GroupBox>

        <GroupBox Header="Large Icons (ListBox)" Grid.Column="1">
            <ListBox ItemsSource="{Binding}">
                <ListBox.Template>
                    <ControlTemplate>
                        <ItemsPresenter/>
                    </ControlTemplate>
                </ListBox.Template>
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <DockPanel Margin="5" Width="120">
                            <StackPanel DockPanel.Dock="Bottom">
                                <TextBlock Text="{Binding ComputerName}" TextAlignment="Center"/>
                                <TextBlock Text="{Binding IPAddress}" TextAlignment="Center"/>
                                <TextBlock Text="{Binding ConnectionTime, StringFormat='HH:mm:ss'}" TextAlignment="Center"/>
                            </StackPanel>
                            <Border Height="60" Width="60" BorderBrush="Black" BorderThickness="1">
                                <TextBlock Text="Some Icon" VerticalAlignment="Center" TextAlignment="Center"/>
                            </Border>
                        </DockPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
                <ListBox.ItemsPanel>
                    <ItemsPanelTemplate>
                        <WrapPanel IsItemsHost="True"/>
                    </ItemsPanelTemplate>
                </ListBox.ItemsPanel>
            </ListBox>
        </GroupBox>

        <GroupBox Header="Tiles (ListBox)" Grid.Column="2">
            <ListBox ItemsSource="{Binding}">
                <ListBox.Template>
                    <ControlTemplate>
                        <ItemsPresenter/>
                    </ControlTemplate>
                </ListBox.Template>
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <DockPanel Margin="5" Width="120">
                            <Border Height="40" Width="50" BorderBrush="Black" BorderThickness="1" DockPanel.Dock="Left">
                                <TextBlock Text="Some Icon" VerticalAlignment="Center" TextAlignment="Center"/>
                            </Border>
                            <StackPanel>
                                <TextBlock Text="{Binding ComputerName}" TextAlignment="Center"/>
                                <TextBlock Text="{Binding IPAddress}" TextAlignment="Center"/>
                                <TextBlock Text="{Binding ConnectionTime, StringFormat='HH:mm:ss'}" TextAlignment="Center"/>
                            </StackPanel>
                        </DockPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
                <ListBox.ItemsPanel>
                    <ItemsPanelTemplate>
                        <WrapPanel IsItemsHost="True"/>
                    </ItemsPanelTemplate>
                </ListBox.ItemsPanel>
            </ListBox>
        </GroupBox>

    </Grid>
</Window>

如您所见,我绝不会在代码中操纵 UI 元素。这使代码保持简洁和良好的分离,因为应用程序逻辑/数据绝不依赖于 UI 元素的状态。

此外,在这个例子中可以看到“将几个不同的视图绑定到同一个视图模型”的概念,在这种情况下就是它ObservableCollection本身。

这是适用于所有事物的“WPF”方法。您几乎不必在代码中操作 UI 元素,至少在应用程序逻辑或数据方面不需要。

只需将我的代码复制并粘贴到 a 中File -> New Project -> WPF Application,然后自己查看结果。

于 2013-03-10T15:58:05.500 回答