我有一个异步服务器侦听本地网络上的客户端。当每个客户端向服务器发送连接消息时,我希望服务器在表中显示客户端的名称。如何将表格/网格添加到vb.net/C# WPF窗口?
假设我已经有客户端名称和IP地址作为字符串ClientDetails用_分隔“PC5_192.168.1.10”
* 编辑*
我想要什么
随着客户加盟,我想每一个客户作为新行添加到表/格。
我正在使用WPF。无论是vb.net或C#的答案都会很好,我可以自己翻译它。
我有一个异步服务器侦听本地网络上的客户端。当每个客户端向服务器发送连接消息时,我希望服务器在表中显示客户端的名称。如何将表格/网格添加到vb.net/C# WPF窗口?
假设我已经有客户端名称和IP地址作为字符串ClientDetails用_分隔“PC5_192.168.1.10”
* 编辑*
我想要什么
随着客户加盟,我想每一个客户作为新行添加到表/格。
我正在使用WPF。无论是vb.net或C#的答案都会很好,我可以自己翻译它。
我准备了一个“WPF方式”的小例子来做到这一点。 它看起来像这样在我的电脑:
进出口使用随机值作为数据源:我通过使用Action<Connection>
委托给加了一个间接层
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);
}
}
公告保持顾虑的分离。 “监听者”负责监听传入连接,添加新连接时应该怎么做不在其范围之内。
这是模型类:
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));
}
}
这是在Window代码隐藏:
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
行动拉姆达通过Dispatcher
将该项目添加到ObservableCollection
UI线程。
最后,这是整个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元素的状态。
此外,在这个例子中可以看到“将几个不同的视图绑定到相同的ViewModel”的概念,在这种情况下是ObservableCollection
本身。
这是一切的“WPF”方法。您几乎不需要在代码中操作UI元素,至少不会考虑应用程序逻辑或数据。
只需将我的代码复制并粘贴到File -> New Project -> WPF Application
中即可自行查看结果。
喔!这是一个verrrrry详细的答案! A ++ ..我会试试这个。 – 2013-03-10 16:01:36
好的答案队友! – failedprogramming 2013-03-10 23:45:18
1 - 如果您使用的是WPF。标记你的问题WPF。 2 - 请不要将WPF'Window'称为“表单”。这是对我的信仰和价值的侮辱。3 - “DataGrid”与数据库无关。 – 2013-03-10 14:58:00
@HighCore竖起你的评论! :) – 2013-03-10 14:58:47
我现在称之为“窗口”,以帮助降低血压 – 2013-03-10 14:59:36