Sorrry guys, I'm stuck here.
I have a few grids, I also have CollectionViewSource objects associated with those grids.
Now, I'm trying to apply CollectionViewSource.SortDescriptions in ColumnHeaderClick method, and now I have to define almost the same method for each grid.
But the only thing I really need is to obtain in which Grid is happenning.
How to get that, I have no idea. Help me please.
VisualTreeHelper.GetParent didn't work.
I think, probably, the best thing would be to derive your own grid control, adding the common functionality that you want. as for finding the the column that was clicked, here is some source code....
protected override void OnPreviewMouseLeftButtonUp(MouseButtonEventArgs e)
{
base.OnPreviewMouseLeftButtonUp(e);
if ( e.OriginalSource is GridViewColumnHeader)
{
GridViewColumn col = ((GridViewColumnHeader)e.OriginalSource).Column as GridViewColumn;
DoStuffWithYourColumn( col );
}
}
oh, and one thing, you really should use the custom sorter instead of sort descriptions--sort descriptions are REALLY slow. take a look at this article for more information on the subject.
Oh.. it's turned out that it's possible to change the SortDesriptions directly in
(((System.Windows.Controls.ListBox)(sender)).Items)
Related
How can I add dynamically a grid into another grid? I can't do this:
myGrid.Children.Add(dg);
Because I don't have the instance of this grid - I'm using MVVM.
Please Help.
I assume, since you mention MVVM, that you want to accomplish this from your View Model?
In that case my suggestion is to send a message from the View Model to the View.
In the View you add a subscription to this message and add the Grid from there.
You could do it something like this, in its most simple form. This would be using the excellent MVVM Light framework:
ViewModel.cs:
private void CreateGrid()
{
Messenger.Default.Send<NotificationMessage>(new NotificationMessage("CreateGrid"));
}
View.xaml.cs:
Messenger.Default.Register<NotificationMessage>(this, nm =>
{
if (nm.Notification != "CreateGrid") return;
// Create grid here
});
If you're dynamically adding controls at runtime, the short answer is that you probably aren't going to be successful doing that via MVVM. Dropping that into the codebehind may be your best bet-- without knowing what kind of app you're building, it is hard to pass judgement and demand loudly that you MUST use MVVM.
That being said, I rarely find myself in a situation with WPF where I have to do dynamic control manipulation like that. Instead, I wind up using different WPF constructs (ListBox, ContentControl, ItemsControl, etc.), along with things like ItemTemplates to get what I want.
Again, without knowing more about what you're trying to accomplish, it's difficult to give any kind of prescriptive guidance.
I'm trying to implement a drag-drop function to a usercontrol.
I've managed to get this working properly with the use of google, however, when dropping a control I wish to find every similar type controls that might be or might not be under it.
My current way would be check every control and see if it's under the dropped control. But I wonder if there is a better way, like a find control function which can check for controls within a given range?
you could use this function:
http://msdn.microsoft.com/en-us/library/system.windows.media.visualtreehelper.findelementsinhostcoordinates%28v=vs.95%29.aspx
void xy_MouseMove(object sender, MouseEventArgs e)
{
if (m_IsDraging)
{
var res = VisualTreeHelper.FindElementsInHostCoordinates(e.GetPosition(null), elemenetWhichChildrenYouWantToCheck);
//... check res for drop elements and react
}
}
Or you can just use this function only in MouseLeftButtonUp event
Well..
First, the Logical Tree is the tree of sub-controls a control is made of.
Second, check this post
This one is a follow-up question.
I filter the top level nodes of a TreeView control like shown below.
private void ApplyFilterHandler(object sender, RoutedEventArgs e)
{
if (_filterCheckBox.IsChecked.Value)
CollectionViewSource.GetDefaultView(TopLevelNodes).Filter += MyFilter;
else
CollectionViewSource.GetDefaultView(TopLevelNodes).Filter -= MyFilter;
}
.
<TreeView ItemsSource="{Binding TopLevelNodes}">
...
</TreeView>
When the user applies the filter all nodes get collapsed.
Question
How can I hide certain nodes in a tree while retaining the expand state of the other nodes?
Can someone explain, what happens internally on ICollectionView.Filter += MyFilter.
Thanks for your time.
In cases such as this Reflector is always your friend. I presume that ICollectionView.Refresh() is called internally to reflect the changes caused by adding/removing a filter. This effectively re-enumerates the nodes in the TreeView.
To compensate for this you can always grab the state of all tree items and re-apply them after a refresh. This may not be the easy solution you were looking for.
You may also want to try to set MyFilter once and call ICollectionView.Refresh() programmatically. Your MyFilter should then filter according to _filterCheckBox.IsChecked value. This could make a difference but these are all merely ideas. You must try them yourself.
I can't believe I am stumped with this fairly straightforward thing. I originally posted this in the WPF datagrid codeplex discussions but got no response. So I am trying here:
I can't seem to find a way to do this. I create a datagrid whose datacontext is initially filled with rows from a table. I have implemented a search functionality that will return some rows based on a condition. Suppose I want to display only those rows, how do I destroy the initially created datacontext and add the newly filtered collection?
I naively started doing it like this:
(Late Edit: I can't seem to type Generics code here -- the cast in the following line is suppoed to cast datagrid.Items to MyType (for example))
IEnumerable rows = datagrid.Items.Cast();
IEnumerable filteredRows = rows.Where(row => row.someCondition == true);
how do I now make my datagrid display only the filteredRows? Just doing:
datagrid.DataContext = null;
datagrid.DataContext = filteredRows;
doesn't work (it even smells stupid for some reason).
I also need to do the reverse (once I get this working). Some buttonclick should allow the user to "clear" the search results and re-plug the DataContext back to "rows" (in the above snippet).
What am I missing?
I came across similar issue. Needed to re-apply converters on my DataGrid after changing some style values.
For me this worked:
myGrid.Items.Refresh()
It appears to re-apply all of the rules so it may work for you.
myGrid.Items.Refresh() worked for me too, just re-set the context before
public void GridExamsRefresh()
{
grdExamenes.ItemsSource = (this.objPacienteOfContext).Exams;
grdExamenes.Items.Refresh();
}
It seems like some similar problems were encountered in this question. In the comments, he even says setting the datacontext to null and then re-assigning it doesn't work.
Perhaps you have to modify the items collection as mentioned in that answer?
Have you tried setting the ItemsSource property?
I have several datagrid where I need to update the informations. Things is, since more than one person works on the system at the same time, the datagrid need to be refreshed on a regular basis. When I refresh, I lose the sorting that user had.
Is there a way to keep it?
thanks
Just update the contents of the bound collection - don't replace the collection itself. Then you will not get a new CollectionView so your sorting won't be affected.
Note that this is untested, but could you do something like this?
ListCollectionView lcv = (ListCollectionView)CollectionViewSource.GetDefaultView(myDataGrid.ItemsSource);
IComparer mySort = lcv.CustomSort; // assumes you've already set it beforehand
... // stuff happens
lcv.CustomSort = mySort;
I am still learning WPF myself, but hope this is some help...
-Matt.