I would like to get the column name of the cell the same way i did with its content on my loose focus method.I can get the content but not the column header.
private void lostFocus(object sender, RoutedEventArgs e)
{
var jj = sender as DataGridColumnHeader;
var box = sender as TextBox;
if (box != null && box.Text != "0")
{
var ff = jj.Column.Header.ToString();
if (ff == "column1") { amount1 = Int32.Parse(box.Text); }
if (ff == "column2") { amount2 = Int32.Parse(box.Text); }
if (ff == "column3") {amount3 = Int32.Parse(box.Text); }
}
else
{
}
}
xaml code
<toolkit:DataGridTemplateColumn Header="column1" Width="8*">
<toolkit:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBox Padding="0" LostFocus="OnGotFocus" GotFocus="OnGotFocus" />
</DataTemplate>
</toolkit:DataGridTemplateColumn.CellTemplate>
</toolkit:DataGridTemplateColumn>
Getting column header
What you need is already provided here by Fredrik. Basically you need to get all the children of type DataGridColumnHeader existing in the DataGrid. Check the column reference and then get the header.
Further more, i see you are getting the DataGridColumnHeader from sender. In order to reach the DataGrid object you can use a helper method :
public static T FindParent<T>(DependencyObject child) where T : DependencyObject
{
//get parent item
DependencyObject parentObject = VisualTreeHelper.GetParent(child);
//we've reached the end of the tree
if (parentObject == null) return null;
//check if the parent matches the type we're looking for
T parent = parentObject as T;
if (parent != null)
return parent;
else
return FindParent<T>(parentObject);
}
Use it like this:
DataGrid parentGrid = FindParent<DataGrid>(sender as DataGridColumnHeader );
or starting from TextBox
DataGrid parentGrid = FindParent<DataGrid>(sender as TextBox);
I am not exactly sure about your scenario.
Updated Xamal... set the textbox name to be the same as header name
<toolkit:DataGridTemplateColumn Header="column1" Width="8*">
<toolkit:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBox Padding="0" Name="column1" LostFocus="OnGotFocus" />
</DataTemplate>
</toolkit:DataGridTemplateColumn.CellTemplate>
</toolkit:DataGridTemplateColumn>
then just got the name from my sender.... simplicity works
private void lostFocus(object sender, RoutedEventArgs e)
{
var box = sender as TextBox;
if (box != null && box.Text != "0")
{
var name = box.Name.ToString();
if (name == "column1") { amount1 = Int32.Parse(box.Text); }
if (name == "column2") { amount2 = Int32.Parse(box.Text); }
if (name == "column3") {amount3 = Int32.Parse(box.Text); }
}
else
{
}
}
Thanks for the help https://stackoverflow.com/users/2047469/olaru-mircea
Related
I have treeview inside my Listview like below
<ListView x:Name="LvItemDisplay" ItemsSource="{Binding itemDisplayList}" SelectionChanged="LvItemDisplay_SelectionChanged">
<ListView.ItemTemplate>
<DataTemplate x:Name="dtItemDisplay">
<TreeView x:Name="TvItemDisplay" Background="Transparent" ItemsSource="{Binding itemDisplayList}" MouseDown="TvItemDisplay_MouseDown_1" SelectedItemChanged="TvItemDisplay_SelectedItemChanged" >
.
.
.
I have click event for both treeview and listview. both of it when click it will popup a dialog box that user can edit that will binding from them.
the problem is, whenever user want to click the treeview user need to click on the listview first to get the SelectedItem. if not nothing will happen since the SelectedItem will be null.
this is the code behind for listview
private void LvItemDisplay_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ListViewItem listViewItem = (ListViewItem)(LvItemDisplay.ItemContainerGenerator.ContainerFromItem(LvItemDisplay.SelectedItem));
TreeView treeView = null;
DialogHost dialogHost = null;
if (LvItemDisplay.SelectedIndex != -1)
{
if (listViewItem != null)
{
//get the listViewItem's template parent
ContentPresenter templateParent = GetFrameworkElementByName<ContentPresenter>(listViewItem);
//get the DataTemplate that treeview in.
DataTemplate dataTemplate = LvItemDisplay.ItemTemplate;
if (dataTemplate != null && templateParent != null)
{
treeView = dataTemplate.FindName("TvItemDisplay", templateParent) as TreeView;
if (treeView != null)
{
dialogHost = dataTemplate.FindName("dialogBoxEditQty", templateParent) as DialogHost;
dialogHost.IsOpen = true;
}
}
}
}
}
and for treeview
private void TvItemDisplay_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
ListViewItem listViewItem = (ListViewItem)(LvItemDisplay.ItemContainerGenerator.ContainerFromItem(LvItemDisplay.SelectedItem));
TreeView treeView = null;
DialogHost dialogHost = null;
if (listViewItem != null)
{
//get the listViewItem's template parent
ContentPresenter templateParent = GetFrameworkElementByName<ContentPresenter>(listViewItem);
//get the DataTemplate that treeview in.
DataTemplate dataTemplate = LvItemDisplay.ItemTemplate;
if (dataTemplate != null && templateParent != null)
{
treeView = dataTemplate.FindName("TvItemDisplay", templateParent) as TreeView;
}
if (treeView != null)
{
dialogHost = dataTemplate.FindName("dialogBoxEditQty", templateParent) as DialogHost;
dialogHost.IsOpen = true;
}
}
}
save for dialogHost
private void ButtonSave_Click(object sender, RoutedEventArgs e)
{
try
{
// get the current selected item
ListViewItem listViewItem = (ListViewItem)(LvItemDisplay.ItemContainerGenerator.ContainerFromItem(LvItemDisplay.SelectedItem));
DialogHost dialogHost = null;
if (listViewItem != null)
{
.
.
.
I want something like whenever user click on the treeview it will triggered the listview behind /click the listview as well. is it possible ?
You can manualy select the ListView Item
TreeView Selection Changed
private void TvItemDisplay_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
LvItemDisplay.SelectionChanged -= LvItemDisplay_SelectionChanged;
ParentItemSelectionChange(sender, true);
// Your code
ParentItemSelectionChange(sender, false);
LvItemDisplay.SelectionChanged += LvItemDisplay_SelectionChanged;
}
Helper Methods
private FrameworkElement ParentItemSelectionChange(object sender, bool selChange)
{
var frameworkElement = sender as FrameworkElement;
if (frameworkElement != null)
{
var item = FindParent<ListViewItem>(frameworkElement);
if (item != null)
item.IsSelected = selChange;
}
return frameworkElement;
}
public T FindParent<T>(DependencyObject child) where T : DependencyObject
{
DependencyObject parentObject = VisualTreeHelper.GetParent(child);
if (parentObject == null) return null;
T parent = parentObject as T;
if (parent != null)
return parent;
return FindParent<T>(parentObject);
}
I have multiple DataGrids where the first column has a Checkbox and the Header also has a Checkbox. As we've all seen, I want to be able to click the header Checkbox and have it select all of the check boxes below.
<DataGrid x:Name="dgReportTypes_New" Margin="10,140,0,0" Height="175" VerticalAlignment="Top" HorizontalAlignment="Left" Width="216" AutoGenerateColumns="False" SelectionMode="Single" CanUserAddRows="False" MouseUp="DataGrid_MouseUp" KeyDown="DataGrid_KeyDown">
<DataGrid.Columns>
<DataGridCheckBoxColumn IsReadOnly="True" Binding="{Binding IsChecked, UpdateSourceTrigger=PropertyChanged}" ClipboardContentBinding="{x:Null}">
<DataGridCheckBoxColumn.HeaderTemplate >
<DataTemplate>
<CheckBox x:Name="chkSelectAll" IsThreeState="True" Checked="DataGridHeader_Checked" Unchecked="DataGridHeader_Unchecked" Indeterminate="DataGridHeader_Indeterminate" />
</DataTemplate>
</DataGridCheckBoxColumn.HeaderTemplate>
</DataGridCheckBoxColumn>
<DataGridTextColumn IsReadOnly="True" Binding="{Binding Description}" CanUserResize="False" Width="*" />
</DataGrid.Columns>
</DataGrid>
Checked
private void DataGridHeader_Checked(object sender, RoutedEventArgs e)
{
DataGrid dg = SGT.Helpers.ControlHelpers.Generics.FindVisualParent<DataGrid>(sender as DependencyObject, typeof(DataGrid));
for (int i = 0; i < dg.Items.Count; i++)
{
DataGridRow row = (DataGridRow)dg.ItemContainerGenerator.ContainerFromIndex(i);
CheckBox c = ControlHelpers.CheckBoxes.ToggleCheckBox(row, true);
}
e.Handled = true;
}
Unchecked
private void DataGridHeader_Unchecked(object sender, RoutedEventArgs e)
{
DataGrid dg = SGT.Helpers.ControlHelpers.Generics.FindVisualParent<DataGrid>(sender as DependencyObject, typeof(DataGrid));
for (int i = 0; i < dg.Items.Count; i++)
{
DataGridRow row = (DataGridRow)dg.ItemContainerGenerator.ContainerFromIndex(i);
CheckBox c = ControlHelpers.CheckBoxes.ToggleCheckBox(row, false);
}
e.Handled = true;
}
Indeterminate
private void DataGridHeader_Indeterminate(object sender, RoutedEventArgs e)
{
((CheckBox)sender).IsChecked = false;
e.Handled = true;
}
Toggle
public static CheckBox ToggleCheckBox(DataGridRow row, bool? overrideValue)
{
if (row == null)
{
return null;
}
CheckBox c = Generics.FindVisualChild<CheckBox>(row as DependencyObject, typeof(CheckBox));
if (overrideValue != null)
{
c.IsChecked = overrideValue;
}
else
{
c.IsChecked = !c.IsChecked;
}
return c;
}
public static CheckBox ToggleCheckBox(object sender, MouseButtonEventArgs e, bool? overrideValue)
{
DataGridRow row = ItemsControl.ContainerFromElement((DataGrid)sender, e.OriginalSource as DependencyObject) as DataGridRow;
if (row == null)
{
return null;
}
CheckBox c = Generics.FindVisualChild<CheckBox>(row as DependencyObject, typeof(CheckBox));
if (overrideValue != null)
{
c.IsChecked = overrideValue;
}
else
{
c.IsChecked = !c.IsChecked;
}
e.Handled = true;
return c;
}
Find Visual
public static T FindVisualChild<T>(DependencyObject parent, Type type) where T : DependencyObject
{
if (parent == null)
Debug.Print("Parent Null");
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
if (child.GetType() == type)
{
Debug.Print(child.ToString());
return child as T;
}
else
{
T result = FindVisualChild<T>(child, type);
if (result != null)
return result;
}
}
return null;
}
DataGrid Clicked
private void DataGrid_MouseUp(object sender, MouseButtonEventArgs e)
{
CheckBox c = ControlHelpers.CheckBoxes.ToggleCheckBox(sender, e, null);
ValidateCheckAll((DataGrid)sender);
}
Handle Header Checkbox when items Checked/unchecked
private void ValidateCheckAll(DataGrid grid)
{
//HeaderedContentControl
DataGridColumnHeadersPresenter hp = Helpers.ControlHelpers.Generics.FindVisualChild<DataGridColumnHeadersPresenter>(grid, typeof(DataGridColumnHeadersPresenter));
CheckBox c = Helpers.ControlHelpers.Generics.FindVisualChild<CheckBox>(hp, typeof(CheckBox));
c.Checked -= new RoutedEventHandler(DataGridHeader_Checked);
c.Unchecked -= new RoutedEventHandler(DataGridHeader_Unchecked);
c.Indeterminate -= new RoutedEventHandler(DataGridHeader_Indeterminate);
int counter = 0;
for (int i = 0; i < grid.Items.Count; i++)
{
DataGridRow row = (DataGridRow)grid.ItemContainerGenerator.ContainerFromIndex(i);
//row.Item
if (row != null)
{
CheckBox ch = Helpers.ControlHelpers.Generics.FindVisualChild<CheckBox>(row, typeof(CheckBox));
if (ch.IsChecked == true)
{
counter++;
}
}
Debug.Print(counter.ToString() + " of " + grid.Items.Count.ToString());
}
if (counter == 0)
{
c.IsChecked = false;
}
else if (counter == grid.Items.Count)
{
c.IsChecked = true;
}
else
{
c.IsChecked = null;
}
c.Checked += new RoutedEventHandler(DataGridHeader_Checked);
c.Unchecked += new RoutedEventHandler(DataGridHeader_Unchecked);
c.Indeterminate += new RoutedEventHandler(DataGridHeader_Indeterminate);
}
I have everything is working the way I expected, until... I got to a DataGrid that had scrollable data.
PROBLEM: Only the visible CheckBoxes change. I'm using visuals to get the Checkbox and slightly understand why this is happening.
Question: Is there a way to Change the rest of the CheckBoxes out of view?
I changed the way it works completely and added a IsChecked to the data behind. Then I looped through the data and chanced the IsChecked and refreshed the grid
Given a DataGrid with a toggle row details button. Why does it collapse the details whenever a property is changed?
It collapses details whenever an column uses:
UpdateSourceTrigger=LostFocus
Also it collapses it whenever a property is updated in the details view.
Is there a way to keep it open? The row is still selected.
XAML:
RowDetailsVisibilityMode="Collapsed"
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button x:Name="buttonDetails" Content="Hello" ButtonBase.Click="Details_Click"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
C#:
// Load stuff from db
_context.JobCollection.Load();
// Set source with db stuff
jobViewSource.Source = _context.JobCollection.Local;
private void Details_Click(object sender, RoutedEventArgs e)
{
try
{
// the original source is what was clicked. For example
// a button.
DependencyObject dep = (DependencyObject)e.OriginalSource;
// iteratively traverse the visual tree upwards looking for
// the clicked row.
while ((dep != null) && !(dep is DataGridRow))
{
dep = VisualTreeHelper.GetParent(dep);
}
// if we found the clicked row
if (dep != null && dep is DataGridRow)
{
// get the row
DataGridRow row = (DataGridRow)dep;
// change the details visibility
if (row.DetailsVisibility == Visibility.Collapsed)
{
row.DetailsVisibility = Visibility.Visible;
}
else
{
row.DetailsVisibility = Visibility.Collapsed;
}
}
}
catch (System.Exception)
{
}
}
Few suggested changes :
Apply RowDetailsVisibilityMode="Collapsed" to your DataGrid.
You Button click should look like this :
private void Details_Click(object sender, RoutedEventArgs e)
{
DataGridRow row = (DataGridRow)Dgrd1.ItemContainerGenerator.ContainerFromItem(Dgrd1.SelectedItem);
if (row.DetailsVisibility == System.Windows.Visibility.Visible)
row.DetailsVisibility = System.Windows.Visibility.Collapsed;
else
row.DetailsVisibility = System.Windows.Visibility.Visible;
}
I have an editable DataGrid, and I want to impletement "single-click edit" on the datagrid cells, which means you only have to click once to make a datagrid cell editable.
<DataGrid RowHeaderWidth="0" BorderThickness="1,1,1,0" GridLinesVisibility="All"
AutoGenerateColumns="False" CanUserReorderColumns="False" CanUserDeleteRows="False"
EnableColumnVirtualization="False" EnableRowVirtualization="False" SelectionMode="Single"
ItemsSource="{Binding Path=Queries}"
SelectedIndex="{Binding Path=SelectedQueryIndex}"
DataGridCell.GotFocus="DataGridCell_GotFocus">
I added the following code and it works perfectly:
private void DataGridCell_GotFocus(object sender, RoutedEventArgs e)
{
DataGridCell cell = e.OriginalSource as DataGridCell;
if (cell != null)
{
// clear existing selection
((DataGrid)sender).SelectedIndex = -1;
// set cell to edit mode
if (cell.Column.DisplayIndex != 0)
{
((DataGrid)sender).BeginEdit(e);
}
// set focus on inner control
Control control = FindFirstChildControl(cell);
if (control != null)
{
control.Focus();
}
}
}
private Control FindFirstChildControl(DependencyObject obj)
{
Control result = null;
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
DependencyObject childObj = VisualTreeHelper.GetChild(obj, i);
if (childObj != null)
{
if (childObj is Control)
{
result = childObj as Control;
break;
}
else
{
result = FindFirstChildControl(childObj);
if (result != null)
{
break;
}
}
}
}
return result;
}
However, adding this piece of code makes the "shift + tab" (reverse tabbing) keyboard hotkey no longer working on datagrid.
How can I fix it while having the "single click edit" feature?
Thanks!
One way around this (well probably not the best) is to handle "Shift is down" manually like this:
private void DataGridCell_GotFocus(object sender, RoutedEventArgs e)
{
// add this line
if (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift)) return;
....
}
//and this event handler
private void DataGrid_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift))
((DataGrid)sender).CommitEdit();
}
I am trying to get a cell value from the selected item of a silverlight datagrid. In the attached code I can get to the properties of the cell and change its forecolor, but I can not get the value of the cell. Can someone please let me know what I am doing wrong? Many thanks in advance for your help!
private void FindDetails_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
DataGrid dataGrid = sender as DataGrid;
int selectedIndex = dataGrid.SelectedIndex;
if (selectedIndex > -1)
{
FindResult findResult = (FindResult)FindDetailsDataGrid.SelectedItem;
DataGridColumn column = dataGrid.Columns[0];
FrameworkElement fe = column.GetCellContent(dataGrid.SelectedItem);
FrameworkElement result = GetParent(fe, typeof(DataGridCell));
if (result != null)
{
DataGridCell cell = (DataGridCell)result;
//changes the forecolor
cell.Foreground = new SolidColorBrush(Colors.Blue);
//how to get cell value?
}
}
}
private FrameworkElement GetParent(FrameworkElement child, Type targetType)
{
object parent = child.Parent;
if (parent != null)
{
if (parent.GetType() == targetType)
{
return (FrameworkElement)parent;
}
else
{
return GetParent((FrameworkElement)parent, targetType);
}
}
return null;
}
Thanks VooDooChild, see below for my solution using the textblock to get at value.
private void FindDetails_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
DataGrid dataGrid = sender as DataGrid;
int selectedIndex = dataGrid.SelectedIndex;
if (selectedIndex > -1)
{
FindResult findResult = (FindResult)FindDetailsDataGrid.SelectedItem;
DataGridColumn column = dataGrid.Columns[0];
FrameworkElement fe = column.GetCellContent(dataGrid.SelectedItem);
FrameworkElement result = GetParent(fe, typeof(DataGridCell));
if (result != null)
{
DataGridCell cell = (DataGridCell)result;
//changes the forecolor
cell.Foreground = new SolidColorBrush(Colors.Blue);
//how to get cell value?
TextBlock block = fe as TextBlock;
if (block != null)
{
string cellText = block.Text;
MessageBox.Show(cellText);
}
}
}
}
private void FindDetails_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
DataGrid dataGrid = sender as DataGrid;
var item = dataGrid.SelectedItem;
if (item != null)
{
//in here you can get the properties with the "item"'s object
}
}
Have you tried something like this pseudo:
string myString = ((MyNamespace.MyEntity)(myDataGrid.SelectedItem)).myStringProperty;
Try cell.Content
http://msdn.microsoft.com/en-us/library/system.windows.controls.contentcontrol.aspx