WPF User Control doesn't show up in grid - wpf

Im trying to add a UserControl in WPF to a grid, but it doesnt show up when im trying to add via MyGrid.Children.Add(UserControl). So i tried to display the number of childs of my grid and it says 1 after adding the usercontrol. (MyGrid.Children.Clear() doesn't work too. After clearing the grid it says that there are 0 childs left but there are still some UiElements when im compiling my program.)
This problem appears only in 1 function. In an other function (the same class) i can easily add childs to the same grid (myGrid).
My code:
private void AddDateOnClick(object sender, MouseButtonEventArgs e)
{
MyGrid.Children.Clear();
UserControlAddDate ucad = new UserControlAddDate();
MyGrid.Children.Add(ucad);
MessageBox.Show(MyGrid.Children.Count.ToString()); //Only to test if there are some childs
}
When i try to clear this grid in a other function (same class) it clears the grid. Only clearing in this function is a problem. Im not understanding why???

What is this UserControlAddDate? Maybe it is not initialized. That’s why it’s not getting added to the grid..
In that place try to add a textbox to the grid and check if it’s working. If it’s working then it’s the problem with your code.
As mentioned by Ed Plunkett, please try to use templates and databinding. It's the best way to work with WPF.
Try this anyway.
private void AddDateOnClick(object sender, MouseButtonEventArgs e)
{
MyGrid.Children.Clear();
TextBox ucad = new TextBox();
ucad.Text = “TEST”;
MyGrid.Children.Add(ucad);
MessageBox.Show(MyGrid.Children.Count.ToString()); //Only to test if there are some childs
}

Related

Strange problem with the left-click on a Silverlight DataGrid

I am experiencing some very strange mouse-event behaviour when working with Silverlights DataGrid:
What I want to do is simply call some method when the user left-clicks over my DataGrid. That shouldn't be much a problem, but ...
With
public void doLeftClick (object sender, MouseButtonEventArgs e) {
// some code
}
i am defining the EventHandler and with
myDataGrid.MouseLeftButtonDown += doLeftClick;
i am attaching it to the event.
The result of that is that the doLeftClick method only gets called when i left-click over one of the columns of my DataGrid!
When i am doing the exact same code as above only for the right-click instead of the left-click the EventHandler gets called everytime i right-click over my DataGrid regardless where the mouse cursor is, as long it is inside the boundaries of the control (which is what i actually need with the left-click and what's the behavior i would expect from this setting):
public void doRightClick (object sender, MouseButtonEventArgs e) {
// some code
}
myDatagrid.MouseRightButtonDown += doRightClick;
So what am i doing wrong ? What am i forgetting ?
I really would appreciate any help :)
Marc
The click events are not bubbled up. If a child control marks the event as handled it stops.
In this instance the left click is being eaten by the DataGrid cells (in order to select them and/or give focus to edit controls).
Right click is not used by the cells in the same way, so propagates up to the DataGrid control.
The column headers are nice enough to allow the left click to propagate.

Silverlight 4 - Print Items Control

I am building a Silverlight 4 application. This application is going to print the contents of an ItemsControl. This ItemsControl uses an ItemTemplate to render the items bound to the control. In all, I have 500 items that are bound to the control.
Oddly, when I attempt to print the ItemsControl, it seems to cut off after a certain point. I cannot tell when it gets cut off. I just know that it gets cut off. I have a hunch it has something to do with virtualization. However, I'm not sure how to overcome this. Currently, I'm printing the ItemsControl like such:
private void printHyperlink_Click(object sender, RoutedEventArgs e)
{
PrintDocument printDocument = new PrintDocument();
printDocument.BeginPrint +=
new EventHandler<BeginPrintEventArgs>(printDocument_BeginPrint);
printDocument.PrintPage +=
new EventHandler<PrintPageEventArgs>(printDocument_PrintPage);
printDocument.EndPrint +=
new EventHandler<EndPrintEventArgs>(printDocument_EndPrint);
printDocument.Print("My Items");
}
void printDocument_BeginPrint(object sender, BeginPrintEventArgs e)
{}
void printDocument_PrintPage(object sender, PrintPageEventArgs e)
{ e.PageVisual = myItemsControl; }
void printDocument_EndPrint(object sender, EndPrintEventArgs e)
{}
What am I doing wrong? How do I ensure that all of the items in my ItemsControl are printed as they are rendered?
The printing APIs don't automatically paginate items in an ItemsControl for you. Furthermore, if you are printing something that is already in the visual tree, the result may get clipped to match what is being rendered in the window at the time of printing.
To print multiple pages, you'll need to:
Measure to figure out how many items to show on the page
Create visuals that only show the items you want on that page
Pass them into your "e.PageVisual"
Set e.HasMorePages to be true until you're on the last page
All in all, this can be a fair amount of work. If you're just trying to print an ItemsControl with an ItemTemplate, you'll have to do all of the work above. For slightly more sophisticated scenarios (e.g. adding page numbers, headers/footers, etc.), there's even more work to do.
That said, it's possible to build a library over the simple Silverlight printing APIs that does something like this. I recently blogged a control meant to address exactly this scenario (as well as some of the more sophisticated ones).
http://www.davidpoll.com/2010/04/16/making-printing-easier-in-silverlight-4/

Finding the TextBlock that is part of the default control template ComboBox generated through code

I'm trying to find the TextBlock that is inside the control template of a comboBox.
using VisualTreeHelpar.GetChildrenCount is working only if the comboBox is declared in XAML.In that case GetChildrenCount returns 1 and a recursive search is possible.
However, if I declare the combo as a member of the Window class using code, allocated and setting it to its place, the function GetChildrenCount return 0. When I run snoop in this scenario It shows the combo children hierarchy. I want to be able to search the comboBox just as snoop does.
Any help would be appreciated.
code:
ComboBox mCombo = null;
private void Windows_Loaded(object sender, RoutedEventArgs e)
{
mCombo = new ComboBox;
mGrid.Children.Add(mCombo);
Grid.SetRow(mCombo,0);
int count = VisualTreeHelpar.GetChildrenCount(mCombo);
}
Call the ApplyTemplate method of ComboBox. Then, you should be able to find what you need.

Maintain scroll position on updating the ItemSource of a silverlight datagrid

I'm using a DataGrid in my silverlight application to display some data that's refreshed on a timer. My problem is that when this happens the vertical scrollbar in the grid resets to the top, whereas I want it to stay in the same position. Does anyone know how I can make this happen?
I've tried overriding the ItemsSource property on the grid to store the vertical scroll position and then reset it, but this only affects the scrollbar and doesn't force the correct rows to be displayed. Is there a way to force this behaviour?
Here is a similar question about Setting the scroll bar position on a ListBox
After rebinding Silverlight Listbox control how do you get it listbox to scroll to back to the top?
Since the DataGrid also supports a ScrollIntoView method, you should be able to use a similar technique such as
theDataGrid.ItemsSource = data;
theDataGrid.UpdateLayout();
theDataGrid.ScrollIntoView(theDataGrid.SelectedItem, theDataGrid.Columns[0]);
I couldn't find a decent answer last time I looked. I wanted to keep the current element selected in the grid but that wouldn't work on an ICollectionView refresh (I use MVVM and get automatic updates from the server).
ScrollIntoView() was not an option for me because the currently selected item may NOT be in view. Having the CurrentChanged event firing out of control was also quite a bother.
In the end, I used the Infragistics grid and it does just that out of the box. Problem solved for me.
You may have a look at the DevExpress free grid. I think it had the same nice behaviour (I tested it but I can't remember the outcome).
You could try setting the SelectedItem thro the UI thread, so that the UI can refresh itself,
like so
private void Button_Click(object sender, RoutedEventArgs e)
{
Person p = new Person() { Name="sss",Age=11}; //datagird's itemsSource is Collection<person>
people.Add(p);
dg.SelectedItem = p; //dg is my datagrid name
Dispatcher.BeginInvoke(() => { dg.SelectedItem = p; });
}
Im assuming that new rows are loaded thro the ViewModel, so thats why it makes sense to place the BeginInvoke there. Since the ViewModel operations run on a different thread, and just setting the SelectedItem on its own might not work, this has worked for someone else
I've also had issues with this. I solved it by remembering the item I want to scroll to, then re-binding the DataGrid. I handle the LayoutUpdated event in order to implement the desired functionality:
void MyDataGrid_LayoutUpdated(object sender, EventArgs e)
{
// Reference the data item in the list you want to scroll to.
object dataItem = yourDataItem;
// Make sure the item is not null and didn't already scroll to the item.
if (dataItem != null && this.dataItemScrolledTo != dataItem)
{
// Remember the item scrolled to.
this.dataItemScrolledTo = dataItem;
// Scroll datagrid to the desired item.
MyDataGrid.ScrollIntoView(dataItem, MyDataGrid.Columns[0]);
}
}
I've modified CodeMaster's solution so that you don't need a class level variable. Put this code in the method that updates the ItemsSource. It will dynamically create the eventhandler, attach it, then detach it.
EventHandler MyDataGrid_LayoutUpdated = null;
MyDataGrid_LayoutUpdated = (s, e) =>
{
MyDataGrid.ScrollIntoView(dataItem, MyDataGrid.Columns[0]);
MyDataGrid.LayoutUpdated -= MyDataGrid_LayoutUpdated;
};
MyDataGrid.LayoutUpdated += MyDataGrid_LayoutUpdated;

How can I put a Silverlight 3 DataGridCell into edit mode in code?

I want to be able to pick a specific cell in a Silverlight 3.0 DataGrid and put it into edit mode. I can use the VisualTreeManager to locate the cell. How do I switch to edit mode?
Each DataGridCell looks like this in the VisualTreeManager:
System.Windows.Controls.DataGridCell
System.Windows.Controls.Grid
System.Windows.Shapes.Rectangle
System.Windows.Controls.ContentPresenter
System.Windows.Controls.TextBlock
System.Windows.Shapes.Rectangle
System.Windows.Shapes.Rectangle
with the TextBlock containing the text I want to edit.
Update
Following #AnthonyWJones' suggestion, here's how I tried to do this using BeginEdit().
I wanted to keep it simple so I thought I'd pick a column in the first row. Even that proved beyond my SL knowledge! In the end, I get the first row by creating a field called firstRow to hold it:
private DataGridRow firstRow;
added a LoadingRow handler to the DataGrid:
LoadingRow="computersDataGrid_LoadingRow"
and
private void computersDataGrid_LoadingRow(object sender, DataGridRowEventArgs e)
{
if (this.firstRow == null)
this.firstRow = e.Row;
}
and then adding a button to the panel to trigger the edit:
private void Button_Click(object sender, RoutedEventArgs e)
{
this.dataGrid.SelectedItem = this.firstRow;
this.dataGrid.CurrentColumn = this.dataGrid.Columns[4];
this.dataGrid.BeginEdit();
}
I click the button and the correct cell is selected but it doesn't go into edit on the cell. It takes a manual click to achieve that.
I'm not sure why you need to find the DataGridCell using VisualTreeManager nor do I know currently how you would properly start editing . You may get away with simply setting the cell's visual state to editing.
VisualStateManager.GoToState(myDataGridCell, "Editing", true);
I'm not sure how the grid behaves when you do something like the above. You may find things goe a bit pearshaped if you need DataGrid to help you revert changes to a row.
The "standard" approach would be to set the DataGrid SelectedItem property to the item represented by the row, set the CurrrentColum property to the DataGridColumn object that represents to the column in which the cell is found. Then call the BeginEdit method.
I am not able to understand your problem properly, but I had a similar problem
I wanted to make only few of the Grid Cells editable and rest were not. Instead of creating a logic and assigning ReadOnly as true/ false, I did the simple thing.
Mark the whole Grid's cells are writable, IsReadOnly as false
Set the event PreparingCellForEdit and send a callback
When you double click on a cell, it gets in the edit mode
Check whether this cell you want to be editable
If it is allowed to be edited, go ahead
If that cell is ReadOnly, then call CancelEdit
The sample code goes like
namespace foo
{
public class foobar
{
public foobar()
{
sampleGrid = new DataGrid();
sampleGrid.IsReadOnly = false;
sampleGrid.PreparingCellForEdit += new EventHandler<DataGridPreparingCellForEditEventArgs>(sampleGrid_PreparingCellForEdit);
}
void sampleGrid_PreparingCellForEdit(object sender, DataGridsampleGrid_PreparingCellForEditEventArgs e)
{
if (sampleGrid.SelectedItem != null)
{
bool isWritableField = CheckIfWritable()
if (isWritableField == false)
{
sampleGrid.CancelEdit();
}
// continue with your logic
}
}
private DataGrid sampleGrid;
}
}

Resources