BeginEdit of a specific Cell from code behind - wpf

Is possibile begin edit of a specific cell from code behind with DataGrid control (WPF Toolkit)?
I have to enable the celledittemplate of first cell of selected row after a button action...how can I do?

pls, try putting the code below in your button's on click event handler:
DataGridCell cell = GetCell(1, 0);
if (cell != null)
{
cell.Focus();
yourDataGrid.BeginEdit();
}
below is implementation for the GetCell method taken from here Grabing controls from a DataGrid
public DataGridCell GetCell(int row, int column)
{
DataGridRow rowContainer = GetRow(row);
if (rowContainer != null)
{
DataGridCellsPresenter presenter = GetVisualChild<DataGridCellsPresenter>(rowContainer);
// try to get the cell but it may possibly be virtualized
DataGridCell cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(column);
if (cell == null)
{
// now try to bring into view and retreive the cell
gridPersons.ScrollIntoView(rowContainer, gridPersons.Columns[column]);
cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(column);
}
return cell;
}
return null;
}
public DataGridRow GetRow(int index)
{
DataGridRow row = (DataGridRow)gridPersons.ItemContainerGenerator.ContainerFromIndex(index);
if (row == null)
{
// may be virtualized, bring into view and try again
gridPersons.ScrollIntoView(gridPersons.Items[index]);
row = (DataGridRow)gridPersons.ItemContainerGenerator.ContainerFromIndex(index);
}
return row;
}
static T GetVisualChild<T>(Visual parent) where T : Visual
{
T child = default(T);
int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < numVisuals; i++)
{
Visual v = (Visual)VisualTreeHelper.GetChild(parent, i);
child = v as T;
if (child == null)
{
child = GetVisualChild<T>(v);
}
if (child != null)
{
break;
}
}
return child;
}
hope this helps, regards

Related

Why doesn't start MeasureOverride?

I have two custom controls for displaying collections of comments and signatures. Each of these controls has a button for changing display style - show entire collection or just first 4 elements.
When I put these controls in a default WrapPanel - they work fine: expand or collapse depending on user's actions.
In my own custom WrapPanel with new ArrangeOverride function they also work fine.
Now I need WrapPanel with option "LastChildFill" (I found example here) and with custom "WrapDirection" (similar to FlowDirection). First or last element in WrapPanel have to fill all remaining space while it's more than MinWidth of the element.
So I've created third WrapPanel with custom MeasureOverride and ArrangeOverride. And it works as I want, but when I change control display style a collection inside a control changes, but MeasureOverride in my WrapPanel doesn't start until I change window size.
Update: MeasureOverride doesn't start for expanding first or last element which fills remaining space. Collapsing for this element works fine.
I don't understand what thing I have broken with custom MeasureOverride?
Update 2:
I fugured that my problem is similar to this: MeasureOverride not always called on children's property changes.
And attach MeasureOverride code.
public class WrapPanelFlowDirection : WrapPanel
{
public bool LastChildFill
{
get { return (bool)GetValue(LastChildFillProperty); }
set { SetValue(LastChildFillProperty, value); }
}
public static readonly DependencyProperty LastChildFillProperty =
DependencyProperty.Register("LastChildFill", typeof(bool), typeof(WrapPanelFlowDirection), new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.AffectsMeasure));
public WrapDirection WrapDirection
{
get { return (WrapDirection)GetValue(WrapDirectionProperty); }
set { SetValue(WrapDirectionProperty, value); }
}
public static readonly DependencyProperty WrapDirectionProperty =
DependencyProperty.Register("WrapDirection", typeof(WrapDirection), typeof(WrapPanelFlowDirection), new FrameworkPropertyMetadata(WrapDirection.LeftToRight, FrameworkPropertyMetadataOptions.AffectsMeasure));
#region Measure Override
protected override Size MeasureOverride(Size availableSize)
{
var panelSize = new Size(availableSize.Width, 0);
double minWidth = 0;
foreach (FrameworkElement child in this.InternalChildren)
{
child.Measure(availableSize);
minWidth += child.DesiredSize.Width;
}
int firstChildInLine = 0;
double currLineHeight = 0;
double currLineWidth = 0;
UIElementCollection children = this.InternalChildren;
for (int i = 0; i < children.Count; i++)
{
FrameworkElement child = children[i] as FrameworkElement;
if (child == null)
continue;
double w = 0;
if (child.MinWidth == 0)
w = child.DesiredSize.Width;
else
w = child.MinWidth;
if (currLineWidth + w <= availableSize.Width)
{
currLineWidth += w;
currLineHeight = Math.Max(currLineHeight, child.DesiredSize.Height);
}
else
{
MeasureOneLine(firstChildInLine, i - 1, ref currLineHeight, availableSize.Width);
panelSize.Height += currLineHeight;
currLineWidth = w;
currLineHeight = child.DesiredSize.Height;
if (w > availableSize.Width)
{
MeasureOneLine(i, i, ref currLineHeight, availableSize.Width);
panelSize.Height += currLineHeight;
currLineHeight = currLineWidth = 0;
firstChildInLine = i + 1;
}
else
{
firstChildInLine = i;
}
}
}
if (firstChildInLine < children.Count)
{
MeasureOneLine(firstChildInLine, children.Count - 1, ref currLineHeight, availableSize.Width);
panelSize.Height += currLineHeight;
}
if (double.IsInfinity(panelSize.Width))
panelSize.Width = minWidth;
return panelSize;
}
private void MeasureOneLine(int start, int end, ref double height, double totalWidth)
{
UIElementCollection children = this.InternalChildren;
if (WrapDirection == WrapDirection.LeftToRight)
{
for (int i = start; i < end; i++)
{
FrameworkElement child = children[i] as FrameworkElement;
if (child == null)
continue;
double w = 0;
if (child.MinWidth == 0)
w = child.DesiredSize.Width;
else
w = child.MinWidth;
if (i < end)
{
child.Measure(new Size(w, height));
totalWidth -= w;
}
else
{
child.Measure(new Size(totalWidth, double.PositiveInfinity));
height = Math.Max(height, child.DesiredSize.Height);
}
}
}
else
{
for (int i = end; i >= start; i--)
{
FrameworkElement child = children[i] as FrameworkElement;
if (child == null)
continue;
double w = 0;
if (child.MinWidth == 0)
w = child.DesiredSize.Width;
else
w = child.MinWidth;
if (i > start)
{
child.Measure(new Size(w, height));
totalWidth -= w;
}
else
{
child.Measure(new Size(totalWidth, double.PositiveInfinity));
height = Math.Max(height, child.DesiredSize.Height);
}
}
}
}
#endregion
I found solution here : How does a container know when a child has called InvalidateArrange?
And it worked for me.
public static void OnPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
{
UIElement panel= VisualTreeHelper.GetParent(source) as UIElement;
if(panel != null)
{
panel.InvalidateMeasure();
panel.InvalidateArrange();
}
}

How to change DataGridCell value programatically

I have a DataGrid with some rows.Now I want change some cell style, eg:
|red| Hel |/red| |blue| lo |/blue| Everybody.
Here is my GetCell function.
public static T GetVisualChild<T>(Visual parent) where T : Visual
{
T child = default(T);
int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < numVisuals; i++)
{
var v = (Visual) VisualTreeHelper.GetChild(parent, i);
child = v as T;
if (child == null)
{
child = GetVisualChild<T>(v);
}
if (child != null)
{
break;
}
}
return child;
}
public static DataGridRow GetSelectedRow(this DataGrid grid)
{
return (DataGridRow) grid.ItemContainerGenerator.ContainerFromItem(grid.SelectedItem);
}
public static DataGridRow GetRow(this DataGrid grid, int index)
{
var row = (DataGridRow) grid.ItemContainerGenerator.ContainerFromIndex(index);
if (row != null) return row;
// May be virtualized, bring into view and try again.
grid.UpdateLayout();
grid.ScrollIntoView(grid.Items[index]);
row = (DataGridRow) grid.ItemContainerGenerator.ContainerFromIndex(index);
return row;
}
public static DataGridCell GetCell(this DataGrid grid, DataGridRow row, int column)
{
if (row == null) return null;
var presenter = GetVisualChild<DataGridCellsPresenter>(row);
if (presenter == null)
{
grid.ScrollIntoView(row, grid.Columns[column]);
presenter = GetVisualChild<DataGridCellsPresenter>(row);
}
var cell = (DataGridCell) presenter.ItemContainerGenerator.ContainerFromIndex(column);
if (cell == null)
{
grid.ScrollIntoView(row, grid.Columns[column]);
cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(column);
}
return cell;
}
public static DataGridCell GetCell(this DataGrid grid, int row, int column)
{
DataGridRow rowContainer = grid.GetRow(row);
return grid.GetCell(rowContainer, column);
}
When I set DataGridCell content with some value by grid.GetCell(1, 0).Content = "PpppPppp", and then scroll DataGrid, the value is gone!
Why?
Even the value jumps to another cell.So strange.
I want to set the cell with style, so not use the funtion about:
(this.dataGrid1.Items[0] as DataRowView)[0] = "new value";
But:
private void SetBlockStyle(TextBlock block, Dictionary<int, int> section)
{
Brush foreground = Brushes.Red;
int start = 0;
string text = block.Text;
block.Text = "";
foreach (int i in section.Keys)
{
if (text.Length <= i)
{
break;
}
block.Inlines.Add(text.Substring(start, i - start));
start = i;
block.Inlines.Add(new Run(text.Substring(i, section[i]))
{
Foreground = foreground,
FontWeight = FontWeights.Bold
});
start += section[i];
}
if (start < text.Length)
{
block.Inlines.Add(text.Substring(start, text.Length - start));
}
}
Can you give me some advice?

How to get count of only visible colums in a WPF datagrid

How can I get count of only visible columns in a WPF datagrid. I am using the count to navigate through the colums present in the datagrid.
if (getSelectedRow().IsEditing)
{
if (dataGrid.SelectedCells.Count != 0)
{
int columnDisplayIndex = dataGrid.CurrentCell.Column.DisplayIndex + 1;
if (columnDisplayIndex <= dataGrid.Columns.Count)
{
if (columnDisplayIndex == dataGrid.Columns.Count)
{
row.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
nextColumn = dataGrid.ColumnFromDisplayIndex(nextCol(1) - 1);
dataGrid.CurrentCell = new DataGridCellInfo(dataGrid.SelectedItem, nextColumn);
}
else
{
e.Handled = true;
nextColumn = dataGrid.ColumnFromDisplayIndex(nextCol(columnDisplayIndex));
dataGrid.CurrentCell = new DataGridCellInfo(dataGrid.SelectedItem, nextColumn);
}
}
}
if (isNotComboBox())
{
dataGrid.CommitEdit();
}
}

Getting new line in wpf

i am having arraylist.let say it contains 15 elements. I am adding these to stack panel. I need to add 3 elements per line. my code is below. I am getting either horizontal or verrtical.Let me know how to do this.
MainWindow w;
public ShopCart(MainWindow m,ArrayList _list)
{
InitializeComponent();
w = m;
int i = 1;
foreach (string cartitems in _list)
{
mystackpanel.Orientation = Orientation.Horizontal;
mystackpanel.Margin.Left.Equals(150);
Label lbl = new Label();
lbl.Name = "Label" + i;
lbl.Height = 30;
lbl.Width = 200;
lbl.Margin.Left.Equals(150);
//lbl.Margin.Top.Equals(150);
lbl.Content = cartitems.ToString();
mystackpanel.Children.Add(lbl);
i++;
int str = mystackpanel.Children.Count;
MessageBox.Show(Convert.ToString(str));
if (str%3 == 0)
{
Button btndelete = new Button();
btndelete.Content = "Delete";
btndelete.Width = 120;
btndelete.Height = 35;
mystackpanel.Children.Add(btndelete);
mystackpanel.Margin.Top.Equals(500);
}
}
Here is some sample code(assuming you already have a list of buttons, and will add outer stack panel to your main control) you can try, you may need to change few things as per your need:
List<Button> buttons = new List<Button>();
StackPanel panel = new StackPanel();
panel.Orientation = Orientation.Horizontal;
int count = 0;
StackPanel innerPanel = new StackPanel();
innerPanel.Orientation = Orientation.Vertical;
foreach (Button button in buttons)
{
innerPanel.Children.Add(button);
++count;
if (count % 3 == 0 && count != 0)
{
panel.Children.Add(innerPanel);
innerPanel = new StackPanel();
innerPanel.Orientation = Orientation.Vertical;
}
}
if (panel.Children.Contains(innerPanel) == false)
{
panel.Children.Add(innerPanel);
}
Although in my opinion the best way will be to have a Grid with n*n row and columns and add your buttons to respective row, columns.

Context Menu on a Group Row in RadGridView

I found one old solution Here.
But GridViewExpander is obsolete in 2009. Proof Here.
How can i implement it (Context Menu on a Group Row in RadGridView) in another way?
No answers... =(
But i found solution.
The are two ways to solve it:
1) If you need custom style for your GridViewGroupRow - read about Templates Structure
2) If not, then just use somthing like this:
<TelerikNavigation:RadContextMenu.ContextMenu>
<TelerikNavigation:RadContextMenu Opened="RadContextMenuOpened" ItemClick="ContextMenuItemClick" x:Name="contextMenu">
</TelerikNavigation:RadContextMenu>
private void RadContextMenuOpened(object sender, RoutedEventArgs e)
{
var menu = (RadContextMenu)sender;
if (menu == null)
return;
var cell = menu.GetClickedElement<GridViewCell>();
var row = menu.GetClickedElement<GridViewRow>();
var groupRow = menu.GetClickedElement<GridViewGroupRow>();
if (cell != null && row != null)
{
if (!cell.DataColumn.IsFrozen)
{
//Code for current cell
}
}
if (groupRow != null)
{
//Code for groupRow
}
}
private void ContextMenuItemClick(object sender, RadRoutedEventArgs e)
{
if (_currentCell != null)
{
//Code for current cell
}
if (_currentGroupRow != null)
{
var menu = (RadContextMenu)sender;
var clickedItem = e.OriginalSource as RadMenuItem;
if (clickedItem != null)
{
foreach (var gridViewRow in _currentGroupRow.ChildrenOfType<GridViewRow>())
{
foreach (var gridViewCellBase in gridViewRow.Cells)
{
if (gridViewCellBase.Column.UniqueName == "PlanObject")
{
var val = gridViewCellBase.DataContext as YourObjectName;
if (val != null)
{
//.....
}
}
}
}
//....
}
}
}

Resources