更新从c#winform中的另一个窗体的gridview列值? [英] update gridview column values from another form in c# winform?

查看:159
本文介绍了更新从c#winform中的另一个窗体的gridview列值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个winforms MainForm GridForm



in MainForm.cs使用 foreach 执行 cmd rmdir 命令一个接一个执行

code>



现在我想显示所有目录名称和它的状态名称它是否处理。

  foreach(listBox1.Items中的var item) 
{
System.Diagnostics.Process.Start(cmd.exe,/ c rmdir+ item);
//希望在GridForm中的gridview中显示哪个文件夹已完成 - 所以uodate状态已完成

var p = proc.ExitCode;
字符串状态;
if(p == 1){status =fail}
else {status =success}
//如何从这里传递状态文本值到GridForm?
我试图像
//网格视图绑定,它会传递项目,状态如何?
GridForm statusForm = new GridForm(listBox1.Items);
GridForm.ShowDialog();
}

问题是我无法将状态值传递给 GridForm

  GridForm.cs 

private void GridForm_Load(object sender ,EventArgs e)
{
DataTable dt = new DataTable();
dt.Columns.Add(Name);
foreach(_ItemList中的字符串项)
{
DataRow row = dt.NewRow();
dt.Rows.Add(items);
}
this.statusGridView.DataSource = dt;
}



我的问题是在MainForm中存在一个
的foreach,它会逐个执行rmdir,现在当我点击
上的执行按钮时,MainForm会执行上面的代码并将打开
另一种形式的GridForm,它显示gridview有两列FolderName
,状态I将从ItemList中获取所有FoolderName,从foreach获得当前状态



现在我怎样才能将它绑定到gridview?

解决方案

可以使用


I have two winforms MainForm and GridForm

in MainForm.cs

executing cmd rmdir command one by one using foreach

Now I want to show list of all directory name and its status name wether it is process or not.

  foreach (var item in listBox1.Items)
  {
     System.Diagnostics.Process.Start("cmd.exe", "/c rmdir " + item);
     // want to show inside gridview in GridForm which folder is done - so uodate status as done

     var p = proc.ExitCode;
     string status;
     if (p == 1){ status = "fail"}
     else {status = "success"}
     // How to pass status text value to GridForm from here? 
     I tried like 
     // grid view bind which will pass items , what about status ?
     GridForm statusForm = new GridForm(listBox1.Items);
     GridForm.ShowDialog();
 }

Problem is I'm unable to pass status value to GridForm

GridForm.cs

   private void GridForm_Load(object sender, EventArgs e)
   {
        DataTable dt = new DataTable();
        dt.Columns.Add("Name");
        foreach (string items in _ItemList)
        {
            DataRow row = dt.NewRow();
            dt.Rows.Add(items);
        }
        this.statusGridView.DataSource = dt;
   }

My question is on MainForm there is a foreach which execute rmdir one by one , now when I click on execute button on MainForm it will execute above foreach code and which will open another form GridForm which shows gridview with two column FolderName and Status I will get all FoolderName from ItemList and Current Status from foreach .

Now how can I bind it to gridview?

解决方案

You can use a BindingSource to have the datagrid respond to changes in the instances of a viewmodel. You can update the property of the specific viewmodel and the BindingSource and databinding framework takes care of repainting and updating rows of any grid.

First create a viewmodel class that implements INotifyPropertyChanged. For brevity I only implemented the Status property to raise the property changed event.

class FolderStatusViewModel:INotifyPropertyChanged
{
    string _status;
    string _folder;

    private void Changed(string propertyName)
    {
        var changed = PropertyChanged;
        if (changed != null)
        {
            changed.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public string Status
    {
        get { return _status; }
        set
        {
            _status = value;
            Changed("Status");
        }
    }
    public string Folder { get; set; }

    public event PropertyChangedEventHandler PropertyChanged;
}

Make sure to compile your project before continuing to the next step.

On your MainForm drag and drop a BindingSource from the Toolbox data category. I named mine folders. Set the DataSource property to a new project datasource and select FolderStatusViewModel as the type.
Set the DataSource of your datagrid to the folders bindingsource.
In your main form load event create a collection (I prefer a List) with an instance of FolderStatusViewModel for each folder

private void MainForm_Load(object sender, EventArgs e)
{
    var folders = new List<FolderStatusViewModel>();
    foreach (var folder in Directory.EnumerateDirectories(@"c:\temp"))
    {
        folders.Add(new FolderStatusViewModel { 
           Folder = folder
        });
    }
    this.folders.DataSource = folders;
 }

On your GridFrom add a DataGrid and BindingSource (I named this one folders again). Set the BindingSource to the same project datasource FolderStatusViewModel and hookup the datagrid with the binding source. The overloaded constructor of GridForm should take an object which we assign to the BindingSource in the Load event:

public partial class GridForm : Form
{
    public GridForm()
    {
        InitializeComponent();
    }

    object source = null;

    public GridForm(object dataSource):this()
    {
        this.source = dataSource;
    }

    private void GridForm_Load(object sender, EventArgs e)
    {
        this.folders.DataSource = source;
    }
}

When you instantiate the GridForm you can simply pass the value of DataSource property of the BindingSource on the mainform to the constructor of the GridForm:

// the grid form takes the DataSource from the folders BindingSource
var grid = new GridForm(this.folders.DataSource);
grid.Show();

 // process each folder, making sure to get an instance of the
 // instances of the ViewModel, in this case by casting 
 // the DataSource object back to the List
foreach(var folderStatus in (List<FolderStatusViewModel>) this.folders.DataSource)
{
    var pi = new ProcessStartInfo();
    pi.FileName ="cmd.exe";
    pi.Arguments ="/c dir /s *.*";
    pi.CreateNoWindow = true;

    var p =  new Process(); 
    p.EnableRaisingEvents = true;
    p.Exited += (s,ee) => { 
        // here the instance of a FolderStatusViewModel
        // gets its Status property updated
        // all subscribers to the PropertyChanged event
        // get notified. BindingSource instances do subscribe to these
        // events, so that is why the magic happens. 
        if (p.ExitCode > 0)
        {
            folderStatus.Status = String.Format("fail {0}", p.ExitCode);
        } 
        else
        {
            folderStatus.Status = "succes";
        }
    };
    p.StartInfo = pi;
    p.Start();
}

By leveraging the BindingSource multiple froms that are databound to any of these instances will get updates simultaneously. The databinding framewoek will do the heavy lifting for you.

If you don't want to use a self created ViewModel but an existing DataTable adapt above code as follows:

The form_load event:

 private void MainForm_Load(object sender, EventArgs e)
 {
     var folders = new DataTable(); 
     folders.Columns.Add("Status");
     folders.Columns.Add("Folder");
     foreach (var folder in Directory.EnumerateDirectories(@"c:\temp"))
     {
         var row = folders.NewRow();
         folders.Rows.Add(row);
         row["Folder"] = folder;
     }
     this.folders.DataSource = folders;
 }

The processing:

// other code omitted
foreach(DataRow folderStatus in ((DataTable) this.folders.DataSource).Rows)
{
     // other code omitted
     p.Exited += (s,ee) => { 
         if (p.ExitCode > 0)
         {
             folderStatus["Status"] = String.Format("fail {0}", p.ExitCode);
         } 
         else
         {
             folderStatus["Status"] = "succes";
         }
     };
     // other code omitted
}

As the DataGrid has now no way to know which columns will exist you have to explicitly add those to each datagrid AND set the DataPropertyName of each Column:

这篇关于更新从c#winform中的另一个窗体的gridview列值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆