I have several radio buttons that are dynamically populated on a form and I have set a click event on the dynamically created radio buttons. On click i get a returned value as follows through debugging (eg) "sender { Text = "this is answer one" + Checked = "True"} using code as follows:
//Radio button click:
void Form1_Click(object sender, EventArgs e)
{
RadioButton rb = sender as RadioButton;
string radioButtonValue = rb.Text;
if (radioButtonValue != String.Empty)
{
}
}
The debug values are returned via "RadioButton rb = sender as RadioButton;" - the diffrent radio buttons text is set via a dataset that I call in a local dataset that loops through the dataset and and sets the radio button text accordingly (eg):
for (int i = 0; i < _dataSetRadioButtons.Tables["tbl_QuestionnaireAnswer"].Rows.Count; i++)
{
radioButtons[i] = new RadioButton();
radioButtons[i].AutoCheck = true;
radioButtons[i].Text = _dataSetRadioButtons.Tables["tbl_QuestionnaireAnswer"].Rows[i]["tbl_QuestionnaireAnswer_Description"].ToString();
radioButtons[i].Location = new System.Drawing.Point(60, 20 + i * 20);
radioButtons[i].Click += new EventHandler(Form1_Click);
panel.Controls.Add(radioButtons[i]);
}
So: wat id like to know is on the radio button click (Form1_Click) event is it possible to return the primary key of the of the selected radio button that I choose and not just the sender { Text = "this is answer one" + Checked = "True"} as I would like to use the primarykey in that dataset to write back to my Database.
Thanks in advance.
Kind regards
geo
Most winforms controls contain the Tag property that is used to contain custom user data in the control. You can read more at: http://msdn.microsoft.com/en-us/library/system.windows.forms.control.tag.aspx
So, your solution should be simpler and more concise like this:
for (int i = 0; i < _dataSetRadioButtons.Tables["tbl_QuestionnaireAnswer"].Rows.Count; i++)
{
radioButtons[i] = new RadioButton();
radioButtons[i].AutoCheck = true;
radioButtons[i].Location = new System.Drawing.Point(60, 20 + i * 20);
radioButtons[i].Tag = _dataSetRadioButtons.Tables["tbl_QuestionnaireAnswer"].Rows[i];
radioButtons[i].Click += new EventHandler(Form1_Click);
panel.Controls.Add(radioButtons[i]);
}
This includes a relevant datarow in the radiobutton. The next thing is to get any data from it you need:
//Radio button click:
void Form1_Click(object sender, EventArgs e)
{
RadioButton radioButton = sender as RadioButton;
if (radioButton == null)
return;
DataRow row = radioButton.Tag as DataRow;
if (row == null)
return;
/* Post any processing here. e.g.
MessageBox.Show(row["ID"].ToString());
*/
}
This way you have all the data and it's strongly typed, which is a good thing.
Related
I would like to update row of datagrid when selection is changed.
private void DataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
Strint rowID = ((String)((DataGrid)sender).SelectedValue);
RadekTabulky row = Client.getRadek(rowID);
if(row != null)
{
dataGrid.SelectionChanged -= DataGrid_SelectionChanged;
int index = dataGrid.SelectedIndex;
viewModel.Sumy = new SumStorage(viewModel.Soubor, viewModel.Radky);
dataGrid.SelectedIndex = index;
dataGrid.SelectionChanged += DataGrid_SelectionChanged;
}
}
I wrote this simple code. But when I click on row, the row is selected, updated but it looks like grid lost focus and I cannot see which row is selected. When I click again at same row, it will get that blue color indicating it is selected.
Is there a way how to update viewModel without losing this focus?
Afternoon,
I have a search button which searches the list of the users is either by IDnumber,Username or department.
I have 2 list view which the users clicks and it load the selected user to the second list view. now the problem is after u clicked users from listview1 and u went to type ID,Username or select department and click search...It clears all the users you selected and bring new users u where searching.
I want to be able to select the users and be able to search without losing my current selected users from the listview
my code ;
//search button
private void Searchbutton_Click(object sender, EventArgs e)
{
try
{
listView1.Items.Clear();
string sID = string.IsNullOrEmpty(txtUserID.Text) ? null : txtUserID.Text;
string sDepartment;
if (cboDepartment.SelectedItem != null)
{
sDepartment = cboDepartment.SelectedItem.ToString();
}
else
{
sDepartment = "";
}
oConnection = new SqlConnection(_connectionString);
oCommand = new SqlCommand(#"Select us.sFieldValue5, u.sUserName, d.sName, TB_USER_CUSTOMINFO.sFieldValue2
From TB_USER u(nolock)
left join [TB_USER_CUSTOMINFO] us(nolock) on us.nUserIdn = u.nUserIdn
left join TB_USER_CUSTOMINFO on u.nUserIdn = TB_USER_CUSTOMINFO.nUserIdn
left join TB_USER_DEPT d(nolock) on d.nDepartmentIdn = u.nDepartmentIdn
where u.sUserName like '%'+ISNULL(#UserName,u.sUserName)+'%'
and us.sFieldValue5 = isnull(#IDNumber,us.sFieldValue5)
and d.sDepartment like '%'+isnull(#Department,d.sDepartment)+'%'", oConnection);
oCommand.Parameters.AddWithValue("UserName", string.IsNullOrEmpty(txtUsername.Text) ? DBNull.Value : (object)txtUsername.Text);
oCommand.Parameters.AddWithValue("IDNumber", string.IsNullOrEmpty(txtUserID.Text) ? DBNull.Value : (object)txtUserID.Text);
oCommand.Parameters.AddWithValue("Department", string.IsNullOrEmpty(sDepartment) ? DBNull.Value : (object)sDepartment);
oConnection.Open();
oDataset = new System.Data.DataSet();
SqlDataReader oReader = oCommand.ExecuteReader();
while (oReader.Read())
{
ListViewItem item1 = new ListViewItem(oReader[1].ToString());
item1.SubItems.Add(oReader[2].ToString());
item1.SubItems.Add(oReader[3].ToString());
item1.SubItems.Add(oReader[0].ToString());
listView1.Items.AddRange(new ListViewItem[] {item1});
}
oReader.Close();
oConnection.Close();
}
//selected users
private void listView1_ItemChecked(object sender, ItemCheckedEventArgs e)
{
if (e.Item.Checked == true)
{
ListViewItem l = listView1.Items[e.Item.Index];
int i = l.SubItems.Count;
string sValue1 = l.SubItems[1].Text;
string sValue2 = l.SubItems[2].Text;
string sValue3 = l.SubItems[3].Text;
ListViewItem item1 = new ListViewItem(l.SubItems[0].Text.ToString());
item1.SubItems.Add(sValue3);
item1.SubItems.Add(sValue2);
item1.SubItems.Add(sValue1);
listView2.Items.AddRange(new ListViewItem[] { (ListViewItem)l.Clone() });
}
else if (e.Item.Checked == false)
{
ListViewItem l = listView1.Items[e.Item.Index];
foreach (ListViewItem i in listView2.Items)
{
if (i.SubItems[0].Text == l.SubItems[0].Text.ToString())
{
listView2.Items.Remove(i);
}
}
}
}
ListView remember which ListViewItems were checked. As soon as you say Items.Clear(), all that knowledge is lost.
To solve your problem, you will need to remember which users were checked, do your refresh, then go through and mark each user as checked again.
To do those steps, you really need to separate your model from your view. Create a User model object to hold the actual data, then populate your ListView with data from your model. When the user does another search, update or refresh your model objects, then rebuild your view.
Doing this model/view separation is a little more work up front, but future generations of maintenance programmers will bless your name.
BTW, ObjectListView -- an open source wrapper around a .NET ListView -- makes creating a fully functional ListView from a list of model objects trivially easy.
What I'm trying to do it a TreeView that have several columns. The first column is a ComboBox, which means that I use Gtk.CellRendererCombo. The thing is, when I selected a value from the ComboBox, I'd like the Text from the cell to change from "" to the value I just selected. It feasible if at the Gtk.CellRendererCombo.Edited event I set the columns Text field to the EditedArgs.NewText.
The problem is, each time I set a value, I create a new row, and I'd like the Text Field to act like it does in the Gtk.CellRendererText, but it doesn't. It's not a different value for each row at that column, but the same value as setted in the Gtk.CellRendererCombo.Text
The Gtk.CellRenderer should not contain any state, so OK, using the Text field is a really bad idea from what I'm trying to do.
But if I set some value from the Gtk.ListStore that is the Model of my TreeView (Which is different from the Model for the Gtk.CellRendererCombo). The values setted will never show at the Column of the ComboBox.
class Program
{
private static Gtk.TreeView treeview = null;
static void OnEdited(object sender, Gtk.EditedArgs args)
{
Gtk.TreeSelection selection = treeview.Selection;
Gtk.TreeIter iter;
selection.GetSelected(out iter);
treeview.Model.SetValue(iter, 0, args.NewText); // the CellRendererCombo
treeview.Model.SetValue(iter, 1, args.NewText); // the CellRendererText
//(sender as Gtk.CellRendererCombo).Text = args.NewText; // Will set all the Cells of this Column to the Selection's Text
}
static void Main(string[] args)
{
Gtk.Application.Init();
Gtk.Window window = new Window("TreeView ComboTest");
window.WidthRequest = 200;
window.HeightRequest = 150;
Gtk.ListStore treeModel = new ListStore(typeof(string), typeof(string));
treeview = new TreeView(treeModel);
// Values to be chosen in the ComboBox
Gtk.ListStore comboModel = new ListStore(typeof(string));
Gtk.ComboBox comboBox = new ComboBox(comboModel);
comboBox.AppendText("<Please select>");
comboBox.AppendText("A");
comboBox.AppendText("B");
comboBox.AppendText("C");
comboBox.Active = 0;
Gtk.TreeViewColumn comboCol = new TreeViewColumn();
Gtk.CellRendererCombo comboCell = new CellRendererCombo();
comboCol.Title = "Combo Column";
comboCol.PackStart(comboCell, true);
comboCell.Editable = true;
comboCell.Edited += OnEdited;
comboCell.TextColumn = 0;
comboCell.Text = comboBox.ActiveText;
comboCell.Model = comboModel;
comboCell.WidthChars = 20;
Gtk.TreeViewColumn valueCol = new TreeViewColumn();
Gtk.CellRendererText valueCell = new CellRendererText();
valueCol.Title = "Value";
valueCol.PackStart(valueCell, true);
valueCol.AddAttribute(valueCell, "text", 1);
treeview.AppendColumn(comboCol);
treeview.AppendColumn(valueCol);
// Append the values used for the tests
treeModel.AppendValues("comboBox1", string.Empty); // the string value setted for the first column does not appear.
treeModel.AppendValues("comboBox2", string.Empty);
treeModel.AppendValues("comboBox3", string.Empty);
window.Add(treeview);
window.ShowAll();
Gtk.Application.Run();
}
}
I'd like the Cell of the ComboBox in which the selection has been made to show the value, but continue to be editable for later changes.
If someone has a way of doing this, I would be very grateful for you input. thanks.
Update:
What I think, because Gtk.CellRendererCombo inherits from Gtk.CellRendererText it just ignores the value setted in the cell. Now, I guess I could create a custom MyCellRendererCombo that inherits from Gtk.CellRendererCombo and use the value setted in the cell when supplied for the rendering, but the documentation on the difference between Gtk.CellRendererText and Gtk.CellRendererCombo is quite slim... I guess I should visit the implementation in C to know the details.
Ok, I've found a solution to my problem, I use a "hidden" column in which I read the "text" value. The hidden column contains the Gtk.CellRendererText, the Gtk.CellRendererCombo must have an Attribute Mapping with the new Column.
The resulting code is below:
class Program
{
private static Gtk.TreeView treeview = null;
static void OnEdited(object sender, Gtk.EditedArgs args)
{
Gtk.TreeSelection selection = treeview.Selection;
Gtk.TreeIter iter;
selection.GetSelected(out iter);
treeview.Model.SetValue(iter, 1, args.NewText); // the CellRendererText
}
static void Main(string[] args)
{
Gtk.Application.Init();
Gtk.Window window = new Window("TreeView ComboTest");
window.WidthRequest = 200;
window.HeightRequest = 150;
Gtk.ListStore treeModel = new ListStore(typeof(string), typeof(string));
treeview = new TreeView(treeModel);
// Values to be chosen in the ComboBox
Gtk.ListStore comboModel = new ListStore(typeof(string));
Gtk.ComboBox comboBox = new ComboBox(comboModel);
comboBox.AppendText("<Please select>");
comboBox.AppendText("A");
comboBox.AppendText("B");
comboBox.AppendText("C");
comboBox.Active = 0;
Gtk.TreeViewColumn comboCol = new TreeViewColumn();
Gtk.CellRendererCombo comboCell = new CellRendererCombo();
comboCol.Title = "Combo Column";
comboCol.PackStart(comboCell, true);
comboCol.AddAttribute(comboCell, "text", 1);
comboCell.Editable = true;
comboCell.Edited += OnEdited;
comboCell.TextColumn = 0;
comboCell.Text = comboBox.ActiveText;
comboCell.Model = comboModel;
comboCell.WidthChars = 20;
Gtk.TreeViewColumn valueCol = new TreeViewColumn();
Gtk.CellRendererText valueCell = new CellRendererText();
valueCol.Title = "Value";
valueCol.PackStart(valueCell, true);
valueCol.AddAttribute(valueCell, "text", 1);
valueCol.Visible = false;
treeview.AppendColumn(comboCol);
treeview.AppendColumn(valueCol);
// Append the values used for the tests
treeModel.AppendValues("comboBox1", "<Please select>"); // the string value setted for the first column does not appear.
treeModel.AppendValues("comboBox2", "<Please select>");
treeModel.AppendValues("comboBox3", "<Please select>");
window.Add(treeview);
window.ShowAll();
Gtk.Application.Run();
}
}
I have Datagrid and Text Box in my Form. Datagrid is showing me existing items in my stock. I use Text Box to search and set focus to that row which is matching with my Text Box. Now it is working fine when VirtualizingStackPanel.IsVirtualizing="false" but it is very slow and getting a lot RAM resource.
Here is my code for this.
public IEnumerable<Microsoft.Windows.Controls.DataGridRow> GetDataGridRows(Microsoft.Windows.Controls.DataGrid grid)
{
var itemsSource = grid.ItemsSource as IEnumerable;
if (null == itemsSource) yield return null;
foreach (var item in itemsSource)
{
var row = grid.ItemContainerGenerator.ContainerFromItem(item) as Microsoft.Windows.Controls.DataGridRow;
if (null != row) yield return row;
}
}
private void SearchBoxDataGrid_TextChanged(object sender, TextChangedEventArgs e)
{
var row = GetDataGridRows(AssortDataGrid);
/// go through each row in the datagrid
foreach (Microsoft.Windows.Controls.DataGridRow r in row)
{
DataRowView rv = (DataRowView)r.Item;
// Get the state of what's in column 1 of the current row (in my case a string)
string t = rv.Row["Ассортимент"].ToString().ToLower();
if (t.StartsWith(SearchBoxDataGrid.Text.ToLower()))
{
AssortDataGrid.SelectedIndex = r.GetIndex();
AssortDataGrid.ScrollIntoView(AssortDataGrid.SelectedItem);
break;
}
}
}
What I want is to make it VirtualizingStackPanel.IsVirtualizing="true" but in this case my method is not working. I know why it is not working, my code will work only for showing part of Datagrid.
What do you recommend? How to fix this issue? Any idea will be appreciated. If you give any working code it will be fantastic. I hope I could explain my problem.
Virtualization means that WPF will reuse the UI components, and simply replace the DataContext behind the components.
For example, if your Grid has 1000 items and only 10 are visible, it will only render around 14 UI items (extra items for scroll buffer), and scrolling simply replaces the DataContext behind these UI items instead of creating new UI elements for every item. If you didn't use Virtualization, it would create all 1000 UI items.
For your Search to work with Virutalization, you need to loop through the DataContext (DataGrid.Items) instead of through the UI components. This can either be done in the code-behind, or if you're using MVVM you can handle the SeachCommand in your ViewModel.
I did a little coding and make it work. If anyone needs it in future please, use it.
Firstly I am creating List of Products
List<string> ProductList;
Then on Load Method I list all my products to my Product List.
SqlCommand commProc2 = new SqlCommand("SELECT dbo.fGetProductNameFromId(ProductID) as ProductName from Assortment order by ProductName desc", MainWindow.conn);
string str2;
SqlDataReader dr2 = commProc2.ExecuteReader();
ProductList = new List<string>();
try
{
if (dr2.HasRows)
{
while (dr2.Read())
{
str2 = (string)dr2["ProductName"];
ProductList.Insert(0, str2.ToLower ());
}
}
}
catch (Exception ex)
{
MessageBox.Show("An error occured while trying to fetch data\n" + ex.Message);
}
dr2.Close();
dr2.Dispose();
After that I did some changes in SearchBoxDataGrid_TextChanged
private void SearchBoxDataGrid_TextChanged(object sender, TextChangedEventArgs e)
{
int pos = 0;
string typedString = SearchBoxDataGrid.Text.ToLower();
foreach (string item in ProductList)
{
if (!string.IsNullOrEmpty(SearchBoxDataGrid.Text))
{
if (item.StartsWith(typedString))
{
pos = ProductList.IndexOf(item);
AssortDataGrid.SelectedIndex = pos;
AssortDataGrid.ScrollIntoView(AssortDataGrid.SelectedItem);
break;
}
}
}
}
Now it works when VirtualizingStackPanel.IsVirtualizing="true".
That is all.
I have a WPF Datagrid and I'm implementing drag and drop functionality.
The datagrid has a list of "files" and the user can drag them and copy the file to the desktop.
This is done like this:
string[] files = new String[myDataGrid.SelectedItems.Count];
int ix = 0;
foreach (object nextSel in myDataGrid.SelectedItems)
{
files[ix] = ((Song)nextSel).FileLocation;
++ix;
}
string dataFormat = DataFormats.FileDrop;
DataObject dataObject = new DataObject(dataFormat, files);
DragDrop.DoDragDrop(this.myDataGrid, dataObject, DragDropEffects.Copy);
I have two questions:
1. When I want to drag multiple items- this is a problem because after I select a couple and start clicking on one to start dragging- only that gets selected and the other items get deselected. I tried the solution that is given here but for some reason it doesn't work.
2. I want to remove the dragged item from the datagrid after it is copied. The problem is that I don't know how to check if the file was copied or whether the user just dragged it on the screen without copying it.
I hope you can help me solve these problems.
Thanks!
I think this i what you are looking for:
add this code to the DataGrid__PreviewMouseLeftButtonDown event handler:
private void DataGrid_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
this.startingPosition = e.GetPosition(null);
DependencyObject dep = (DependencyObject)e.OriginalSource;
// iteratively traverse the visual tree until get a row or null
while ((dep != null) && !(dep is DataGridRow))
{
dep = VisualTreeHelper.GetParent(dep);
}
//if this is a row (item)
if (dep is DataGridRow)
{
//if the pointed item is already selected do not reselect it, so the previous multi-selection will remain
if (songListDB.SelectedItems.Contains((dep as DataGridRow).Item))
{
// now the drag will drag all selected files
e.Handled = true;
}
}
}
and now the draging won't change you selection.
Have a good luck!
I used that article to write my answer
Improved on finding the row.
Also selecting the clicked row when not dragging is added.
This now behaves exactly as other Microsoft selectors (eg Outlook)
public TreeDataGrid()
{
Loaded += TreeDataGrid_Loaded;
LoadingRow += new EventHandler<DataGridRowEventArgs>(TreeDataGrid_LoadingRow);
}
#region MultiSelect Drag
object toSelectItemOnMouseLeftButtonUp;
void TreeDataGrid_LoadingRow(object sender, DataGridRowEventArgs e)
{
e.Row.PreviewMouseLeftButtonDown += new MouseButtonEventHandler(Row_PreviewMouseLeftButtonDown);
e.Row.PreviewMouseLeftButtonUp += new MouseButtonEventHandler(Row_PreviewMouseLeftButtonUp);
}
void Row_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
DataGridRow row = (DataGridRow)sender;
toSelectItemOnMouseLeftButtonUp = null; // always clear selecteditem
if (SelectedItems.Contains(row.Item)) //if the pointed item is already selected do not reselect it, so the previous multi-selection will remain
{
e.Handled = true; // this prevents the multiselection from disappearing, BUT datagridcell still gets the event and sets DataGrid's private member _selectionAnchor
toSelectItemOnMouseLeftButtonUp = row.Item; // store our item to select on MouseLeftButtonUp
}
}
void Row_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
DataGridRow row = (DataGridRow)sender;
if (row.Item == toSelectItemOnMouseLeftButtonUp) // check if it's set and concerning the same row
{
if (SelectedItem == toSelectItemOnMouseLeftButtonUp) SelectedItem = null; // if the item is already selected whe need to trigger a change
SelectedItem = toSelectItemOnMouseLeftButtonUp; // this will clear the multi selection, and only select the item we pressed down on
typeof(DataGrid).GetField("_selectionAnchor", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(this, new DataGridCellInfo(row.Item, ColumnFromDisplayIndex(0))); // we need to set this anchor for when we select by pressing shift key
toSelectItemOnMouseLeftButtonUp = null; // handled
}
}
#endregion