下面我将附上我的窗口所有类(这是wpf)。我将评论我认为是问题/关注/问题的内容,之后我将按照清单顺序解释我的评论。最有帮助的答案将是那些使用代码作为参考回答所列问题的人。我将提供主窗口cs以及RowContainer类(简单管理类)。
以下是gui ...
的图片 public partial class MainWindow : Window
{
public static DebugWindow debugWindow;
public static MainWindow mainWindow;
public static Dispatcher mainWindowDispacter;
private Object locker = new Object();
public ConnectionHandle ConnectionHandler;
public RowContainer[] RowContents;
public MainWindow()
{
InitializeComponent();
mainWindow = this;
mainWindowDispacter = this.Dispatcher;
}
public RowContainer RowExists(Client c)
{
if (RowContents == null)
return null;
foreach (RowContainer r in RowContents)
{
if (r.GetClient().getUID().Equals(c.getUID()))
return r;
}
return null;
}
// ----------------1 --------------------
public void RemoveFromRowList(RowContainer r)
{
List<RowContainer> l = new List<RowContainer>();
List<int> usedList = new List<int>();
int deleteRowNumber = r.rowNumber;
foreach (RowContainer rr in RowContents)
{
if (!r.Equals(rr))
{
if (rr.rowNumber > deleteRowNumber)
rr.rowNumber--;
l.Add(rr);
}
}
RowContents = l.ToArray();
}
//----------------------- 2 -------------------
public void AddToRowList(RowContainer r)
{
if (RowContents == null)
{
r.rowNumber = 1;
RowContents = new RowContainer[] { r };
return;
}
List<RowContainer> l = new List<RowContainer>();
List<int> usedList = new List<int>();
foreach (RowContainer rr in RowContents)
{
l.Add(rr);
usedList.Add(rr.rowNumber);
}
Console.WriteLine(usedList.ToString());
int? firstAvailable = Enumerable.Range(1, int.MaxValue)
.Except(usedList)
.FirstOrDefault();
r.rowNumber = (int)firstAvailable;
l.Add(r);
RowContents = l.ToArray();
}
private void onDebugLogClick(object sender, RoutedEventArgs e)
{
if (debugWindow == null)
{
debugWindow = new DebugWindow();
debugWindow.Show();
}
else
{
if (debugWindow.IsVisible)
{
debugWindow.Hide();
}
else
debugWindow.Visibility = Visibility.Visible;
}
}
public BitmapImage ToImage(byte[] array)
{
using (var ms = new System.IO.MemoryStream(array))
{
var image = new BitmapImage();
image.BeginInit();
image.CacheOption = BitmapCacheOption.OnLoad;
image.StreamSource = ms;
image.EndInit();
return image;
}
}
// type 0 - image, 1 - status, 2 - OS, 3 - Idle, 4 - bitaccount
public void UpdateRowContainer(RowContainer r, int type)
{
switch (type)
{
case 0:
BitmapImage image = ToImage(r.Image);
System.Windows.Controls.Image uiImage = (System.Windows.Controls.Image)MyGrid.Children.Cast<UIElement>().First(e => Grid.GetRow(e) == r.rowNumber & Grid.GetColumn(e) == 0);
if (uiImage == null)
{
}
else
{
uiImage.Source = image;
}
break;
case 2:
Label OsLabel = (System.Windows.Controls.Label)MyGrid.Children.Cast<UIElement>().First(e => Grid.GetRow(e) == r.rowNumber & Grid.GetColumn(e) == 5);
OsLabel.Content = r.Os;
break;
case 3:
Label idleLabel = (System.Windows.Controls.Label)MyGrid.Children.Cast<UIElement>().First(e => Grid.GetRow(e) == r.rowNumber & Grid.GetColumn(e) == 3);
idleLabel.Content = r.idle;
break;
}
}
// --------------------------- 3----------------------
public void CreateClientRowContainer(Client c, byte[] imageBytes)
{
RowContainer newContainer = new RowContainer(c);
BitmapImage image = ToImage(imageBytes);
newContainer.Image = imageBytes;
Label cLabel = new Label();
Label osLabel = new Label();
Label stateLabel = new Label();
Label bitAccountLabel = new Label();
Label idleTimeLabel = new Label();
osLabel.Content = "N/A";
stateLabel.Content = "N/A";
bitAccountLabel.Content = "N/A";
idleTimeLabel.Content = "N/A";
cLabel.Content = c.getClientIp();
cLabel.SetValue(Grid.ColumnProperty, 1);
stateLabel.SetValue(Grid.ColumnProperty, 2);
idleTimeLabel.SetValue(Grid.ColumnProperty, 3);
bitAccountLabel.SetValue(Grid.ColumnProperty, 4);
osLabel.SetValue(Grid.ColumnProperty, 5);
int rowCount = this.MyGrid.RowDefinitions.Count;
this.MyGrid.RowDefinitions.Add(new RowDefinition());
Style style = this.FindResource("LabelTemplate") as Style;
Style style2 = this.FindResource("OSTemplate") as Style;
cLabel.Style = style;
stateLabel.Style = style;
bitAccountLabel.Style = style;
idleTimeLabel.Style = style;
osLabel.Style = style2;
cLabel.SetValue(Grid.RowProperty, rowCount);
bitAccountLabel.SetValue(Grid.RowProperty, rowCount);
stateLabel.SetValue(Grid.RowProperty, rowCount);
idleTimeLabel.SetValue(Grid.RowProperty, rowCount);
osLabel.SetValue(Grid.RowProperty, rowCount);
System.Windows.Controls.Image imgIcon = new System.Windows.Controls.Image();
imgIcon.Height = 150;
imgIcon.HorizontalAlignment = HorizontalAlignment.Center;
imgIcon.VerticalAlignment = VerticalAlignment.Top;
imgIcon.Source = image;
MyGrid.Children.Add(cLabel);
MyGrid.Children.Add(idleTimeLabel);
MyGrid.Children.Add(stateLabel);
MyGrid.Children.Add(bitAccountLabel);
MyGrid.Children.Add(osLabel);
ConnectionHandle.SendRequestInformation(c, 3);
imgIcon.SetValue(Grid.ColumnProperty, 0);
imgIcon.SetValue(Grid.RowProperty, rowCount);
MyGrid.Children.Add(imgIcon);
AddToRowList(newContainer);
}
// -------------------- 4 ---------------------
public void RemoveClientGrid(Client c)
{
RowContainer con = RowExists(c);
if (con == null)
return;
if (MyGrid.RowDefinitions.Count < con.rowNumber)
{
RemoveFromRowList(con);
return;
}
Console.WriteLine("Removing row: " + con.rowNumber);
Console.WriteLine("Total rows: " + MyGrid.RowDefinitions.Count);
RowDefinitionCollection defs = MyGrid.RowDefinitions;
foreach (UIElement control in MyGrid.Children)
{
if (Grid.GetRow(control) == con.rowNumber)
{
MyGrid.Children.Remove(control);
}
}
defs.RemoveAt(con.rowNumber);
RemoveFromRowList(con);
}
protected override void OnClosing(CancelEventArgs e)
{
if (debugWindow != null)
debugWindow.Close();
Environment.Exit(Environment.ExitCode);
base.OnClosing(e);
}
private void onServerStartClick(object sender, RoutedEventArgs e)
{
if (ConnectionHandler == null)
{
ConnectionHandler = new ConnectionHandle();
}
else
{
MessageBox.Show("Server Has Already Started!");
}
}
private Client GetRowClient(int row)
{
foreach(RowContainer r in RowContents) {
if (r.rowNumber == row)
return r.client;
}
return null;
}
private void onRefreshMenuClick(object sender, RoutedEventArgs e)
{
MenuItem mi = sender as MenuItem;
if (mi != null)
{
ContextMenu cm = mi.CommandParameter as ContextMenu;
if (cm != null)
{
Grid g = cm.PlacementTarget as Grid;
if (g != null)
{
var p = Mouse.GetPosition(g);
int row = 0;
int col = 0;
double accumulatedHeight = 0.0;
double accumulatedWidth = 0.0;
// calc row mouse was over
foreach (var rowDefinition in g.RowDefinitions)
{
accumulatedHeight += rowDefinition.ActualHeight;
if (accumulatedHeight >= p.Y)
break;
row++;
}
Client c = GetRowClient(row);
if (c != null)
{
ConnectionHandle.SendRequestInformation(c, 1);
ConnectionHandle.SendRequestInformation(c, 4);
}
else
if (debugWindow != null)
debugWindow.LogTextBox.AppendText("Unable to find client!");
}
}
}
}
private void onDisconnectClicked(object sender, RoutedEventArgs e)
{
MenuItem mi = sender as MenuItem;
if (mi != null)
{
ContextMenu cm = mi.CommandParameter as ContextMenu;
if (cm != null)
{
Grid g = cm.PlacementTarget as Grid;
if (g != null)
{
var p = Mouse.GetPosition(g);
int row = 0;
int col = 0;
double accumulatedHeight = 0.0;
double accumulatedWidth = 0.0;
// calc row mouse was over
foreach (var rowDefinition in g.RowDefinitions)
{
accumulatedHeight += rowDefinition.ActualHeight;
if (accumulatedHeight >= p.Y)
break;
row++;
}
Client c = GetRowClient(row);
if (c != null)
{
// ----- RemoveFromClientPool is basically RemoveClientGrid(c) seen above.
ClientHandle.RemoveFromClientPool(c, "Server Requested");
}
else
if (debugWindow != null)
debugWindow.LogTextBox.AppendText("Unable to find client!");
}
}
}
}
}
1)我将此方法标记为RemoveFromRowList只是因为我不确定当我尝试删除行时是否所有行都需要向上移动。行号在RowContainer类中给出并保存。
2)几乎和一个问题一样......我不确定究竟发生了什么,所以我只是插入了一个行号...所以说如果有5个客户端并且第三个在wpf网格上断开连接那么下一个连接的客户端获取第3行?这听起来很傻请告诉我他们刚刚转移,因为4将是3和5将成为4 ...?
3)这是它为网格生成新行的方式。这很丑陋,但似乎工作我唯一关心的是我的第0行采用了我的默认文本。因此,我认为伯爵会在正确的新行开始。因为如果第一个客户端的计数= 1(仅计算我以前的默认行)。
4)我相信这是我的主要问题。删除所有控件和行本身。它似乎正在抛出System.InvalidOperationException。但我也确定我的行编号已关闭......
----总体问题:a)当行离开时行号会发生什么? (新客户端来了,它获得了最后一个位置,那里的所有其他客户端都被连续移动了?) b)如何在wpf中有效删除Grid中的行,包括该行中的所有控件?
我不相信我的RowContainer课程存在问题,因为我可以做到这一切,所以我只能这样做。但它显然不会抛出任何真正的错误。
public class RowContainer
{
public byte[] Image { get; set; }
public String state;
public String ip;
public String Os {get; set;}
public String bitacc;
public String idle {get; set;}
public Client client;
public int rowNumber { get; set; }
public RowContainer(Client c)
{
this.ip = c.getClientIp();
this.client = c;
}
public void SetIdleTime(String time)
{
this.idle = time;
}
public void SetState(String st)
{
this.state = st;
}
public void SetBCAccount(String bc){
this.bitacc = bc;
}
public String GetIp()
{
return this.ip;
}
public String GetBitAccount()
{
return this.bitacc;
}
public Client GetClient()
{
return this.client;
}
public String GetIdleTime()
{
return this.idle;
}
public String GetState()
{
return this.GetState();
}
}
答案 0 :(得分:0)
我想你是WPF的新手,所以我的第一个建议就是腾出一些时间来阅读MVVM。这是WPF的主要优势之一。你可以看一下这个问题 MVVM: Tutorial from start to finish?
关于你的问题,网格控件是一个布局控件,请看这里http://www.wpftutorial.net/GridLayout.html
如果要显示项目列表,最好使用ItemsControl(例如ListBox)。 在这里阅读:http://www.wpf-tutorial.com/list-controls/itemscontrol/这将为您节省维护有效索引和处理行的创建和删除的麻烦。