简体   繁体   中英

Removing Row & All Controls in Same Row

Below I will attach the whole class I have for my window (this is wpf). I will comment what I believe to be issues/concerns/problems and afterwards I will explain my comments below in list order. Most helpful answer will be those who answer listed questions using the code as reference. I will provide main window cs and also RowContainer class (simple management class).

Here is a picture of the 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) I marked this method RemoveFromRowList simply because I am not sure if all the rows need to move up when I try to remove a row. The row numbers are given and held in the RowContainer class.

2) Almost the same concern as one... I am not sure what exactly happens so I just inserted a row number... so say if there are 5 clients and the 3rd one on the wpf grid disconnects then the next client that connects gets row 3? That sounds silly please tell me the they just get shifted as in 4 will be 3 and 5 will become 4...?

3) This is how it generates a new row for the grid. It's ugly but it seems to be working my only concern is really the numbering I have row 0 taken my some default text. So count will start me at the right new row i guess. Since if the first client comes on its count = 1 (only counting the default row i had before).

4) Well I believe this is my main issue. The remove of all controls and the row itself. It seems like its throwing System.InvalidOperationException at the moment. But I am also sure my row numbering is off...

---- Overall issues: a) What happens to row numbers as a row leaves? (new client comes and it gets last spot and all other clients that were there get shifted up a row?) b) How do I efficiently remove a row in Grid on wpf including all controls within that row?

I don't believe there is a problem with my RowContainer class it's just dirty atm as I can do all get;set; but it will obviously not throw any real errors how it is.

 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();
    }
}

I guess you are new to WPF, so my first advise is to free up some time and read about MVVM. this is one of the main advantages in WPF. you can look at that question for example MVVM: Tutorial from start to finish?

regarding your question , Grid control is a layout control take a look here http://www.wpftutorial.net/GridLayout.html

When you want to display a list of items it would be better to use ItemsControl (ListBox for example). read here: http://www.wpf-tutorial.com/list-controls/itemscontrol/ this will save you the hassle of maintaining valid indexes and handling the creating and deletion of rows.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM