I have a fairly standard ListView with a GridView:
<ListView x:Name="ListViewProducts" ItemsSource="{Binding Products}">
<ListView.View>
<GridView>
<GridViewColumn Header="Id" Width="50" DisplayMemberBinding="{Binding Id}"/>
<GridViewColumn Header="Name" Width="200" DisplayMemberBinding="{Binding Name}"/>
</GridView>
</ListView.View>
</ListView>
I'd like to implement infinite scrolling to this ListView, where new items would be loaded as soon as the user scrolls to the bottom of the list. I've tried to get the ScrollViewer of ListView using VisualTreeHelper but ListViewProduct apparently has no children:
VisualTreeHelper.GetChildrenCount(ListViewProducts) // Gives 0
Because the count of children is 0, answers like this won't work: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/794815aa-9a1e-4b57-b097-71d8672f331b/.
How can I detect when the user has scrolled to the bottom of the ListView?
Well I guess you have to fetch the inner ScrollViewer of the ListView, since I think the ScrollViewer is providing the scrolling behavior.
After you managed that, this post is probably going to help you.
Related
There's a ListView in my window that has a number of columns. Some or all of the columns must not be resizable by the user because they already have the optimal width and accidental resizing only makes it worse. Now there's some answers to that question available, but all of them end up with restyling the control. Unfortunately then I end up with numerous pages of XAML code which is highly platform/theme-specific. When I create a copy of the default style with Blend, I get lots of gradients etc that only work on Win7 Aero, but not in XP theme or whatever will come.
So replacing the entire style of a control is not an option. (It hardly ever really is.)
I've already identified the part that needs to be hidden, it's named "PART_HeaderGripper". I've done such things before, removing the running glow and other parts from a ProgressBar with the following code in code-behind:
var glow = progressBar.Template.FindName("PART_GlowRect", progressBar) as FrameworkElement;
if (glow != null) glow.Visibility = visibility;
But this doesn't work with a GridViewColumnHeader because Template.FindName doesn't find anything (returns null). I'm pretty sure there must be a way to modify the visuals at runtime. But I can't figure it out right now. Any idea?
Tested:
<GridViewColumnHeader Content="Value" IsHitTestVisible="False"/>
I had the same issue in one of my projects. I have found a solution, which I think not the best way, but at least works.
I am using some databingind and click events to sort the items, so setting the column to readonly was not a way to go.
Here is the code part from the xml:
<ListView Name="ListWievResults" HorizontalAlignment="Left" Height="526" Margin="10,10,0,0" VerticalAlignment="Top" Width="400" ItemsSource="{Binding Results}" SelectedItem="{Binding SelectedResult}" IsSynchronizedWithCurrentItem="True" SelectionChanged="ListWievResults_SelectionChanged" SelectionMode="Single">
<ListView.View>
<GridView AllowsColumnReorder="False">
<GridView.Columns>
<GridViewColumn DisplayMemberBinding="{Binding Path=Name}" Width="200">
<GridViewColumnHeader Content="Parameter" Click="GridViewColumnHeader_Click" PreviewMouseMove="GridViewColumnHeader_PreviewMouseMove"/>
</GridViewColumn>
<GridViewColumn DisplayMemberBinding="{Binding Path=ID}" Width="100">
<GridViewColumnHeader Content="SAFE ID" Click="GridViewColumnHeader_Click" PreviewMouseMove="GridViewColumnHeader_PreviewMouseMove"/>
</GridViewColumn>
<GridViewColumn DisplayMemberBinding="{Binding Path=Author}" Width="95">
<GridViewColumnHeader Content="Author" Click="GridViewColumnHeader_Click" PreviewMouseMove="GridViewColumnHeader_PreviewMouseMove"/>
</GridViewColumn>
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>
and the related part from th xaml.cs file:
private void GridViewColumnHeader_PreviewMouseMove(object sender, System.Windows.Input.MouseEventArgs e)
{
e.Handled = true;
}
This is not the most beautiful way as the marker will still be there showing that you can resize the column, but at least it does not allow it.
One drawback is that if you want to use the "PreviewMouseMove" event for something else, that will not work.
I really hope that this can help.
I am implementing an application in wpf , MVVM pattern.
I want to implement a listview with objects. These objects contains a list. On default this list contains only 1 object. But in the listview, I want to show that certain object. So the properties of the object in the list. This is my first problem.
But I also have to be able to have more objects in this list. My second problem is that i don't really know how to realise this? And i also have to show the properties of these objects in the listview.
Maybe a treeview? but i don't get how that i got to begin on this..
Someone with some ideas?
You can arbitrarily nest DataTemplates, e.g.
<ListView ItemsSource="{Binding Data}">
<ListView.View>
<GridView>
<GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}"/>
<!-- Internal Manchines list gets its own ListView -->
<GridViewColumn Header="Machines">
<GridViewColumn.CellTemplate>
<DataTemplate>
<ListView ItemsSource="{Binding Machines}">
<ListView.View>
<GridView>
<GridViewColumn Header="Model" DisplayMemberBinding="{Binding Model}"/>
<GridViewColumn Header="Manufacturer" DisplayMemberBinding="{Binding Manufacturer}"/>
</GridView>
</ListView.View>
</ListView>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Occupation" DisplayMemberBinding="{Binding Occupation}"/>
<GridViewColumn Header="Status" DisplayMemberBinding="{Binding Status}"/>
</GridView>
</ListView.View>
</ListView>
This can be improved in terms of alignment, e.g. you could set up a Grid in the DataTemplate with a shared size column to make all lists the same width (making the internal columns align might be a bit hard though)
Further you could define a style to collapse empty lists (which otherwise would show the header without items).
This is my XAML:
<ListView ItemsSource="{Binding Items}">
<ListView.View>
<GridView>
<GridViewColumn Header="Property1" DisplayMemberBinding="{Binding Property1}" />
<GridViewColumn Header="Property2" DisplayMemberBinding="{Binding Property2}" />
</GridView>
</ListView.View>
</ListView>
I want these 2 columns to take up the width of ListView in 1:1 ratio.
How can I achieve this?
Edit: I found this suggestion on MS Connect. This would perfectly solve my problem.
However it is closed as postponed (for 2.5 years now..)
What comes to mind is using internal Grids in the templates which each have a ColumnDefinition with the same SharedSizeGroup, the GridView should then have Grid.IsSharedSizeScope="True" and the columns of the grid view should themselves be unresizable (if that is possible), cannot test that right now so it's a bit sketchy.
Another method would be to bind both Widths of the GridViewColumns to the width of the ListView and then use a custom converter to get an appropriate fraction of that back.
I am trying to implement a ListView with a GridView with sortable columns.
To sort the ListView I hook up the Click event for the GridViewColumnHeaders and adding SortDescriptors to the default view source (similar to what is done in MSDN).
Something like this:
<ListView ItemsSource="MY ITEMS SOURCE BINDING">
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn DisplayMemberBinding="MY DISPLAYMEMBER BINDING">
<GridViewColumnHeader Content="My Header" Click="ColumnHeaderClicked"/>
This all works fine, but I would like to generalize it a bit. To do that I simply derived GridViewColumnHeader and wrote a click-handler. I know there are many sortable list view implementations out there typically deriving from ListView, but I was just wondering if this approach is possible.
Something like this:
<ListView ItemsSource="MY ITEMS SOURCE BINDING">
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn DisplayMemberBinding="MY DISPLAYMEMBER BINDING">
<local:SortableGridViewColumnHeader Content="My Header"/>
For this to work I need to navigate from the SortableGridViewColumnHeader code to the containing ListView in order to set new SortDescriptors.
I tried navigating up the Parent ladder, but the GridViewColumnHeader is not a visual child of my ListView. Surely I could make a dependency property and bind it to the ListView, but there must be a way to navigate to it instead.
How would I do that in code? (I am not looking for answers on how to sort a WPF ListViews in general, I am wondering if it can be done this way).
EDIT
It turned out that what I needed was this parent searcher in the click-handler of my GridViewColumnHeader derivative.
DependencyObject parent = this;
do
{
parent = VisualTreeHelper.GetParent(parent);
if (parent == null) return;
} while (!(parent is ListView));
Now my sorting works like a charm.
There is a much easier way to do that, using an attached property. Check out this article for details.
<ListView ItemsSource="{Binding Persons}"
IsSynchronizedWithCurrentItem="True"
util:GridViewSort.AutoSort="True">
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn Header="Name"
DisplayMemberBinding="{Binding Name}"
util:GridViewSort.PropertyName="Name"/>
<GridViewColumn Header="First name"
DisplayMemberBinding="{Binding FirstName}"
util:GridViewSort.PropertyName="FirstName"/>
<GridViewColumn Header="Date of birth"
DisplayMemberBinding="{Binding DateOfBirth}"
util:GridViewSort.PropertyName="DateOfBirth"/>
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>
I might sound dumb here, but I want to do something really simple. At design time, I want to add columns to a listview control and add some data to it. I need to add combobox in each column of the listview. The thing I am not able to find is where to mention the column number in the listviewitem. Any help appreciated guys.
<ListView IsSynchronizedWithCurrentItem="True" Margin="8,68,304,188"
BorderThickness="2,2,2,2">
<ListView.View>
<GridView>
<GridViewColumn Width="150" Header="Column1"/>
<GridViewColumn Width="150" Header="Column2"/>
</GridView>
</ListView.View>
<ListViewItem>
</ListViewItem>
</ListView>
Each column in the listviewitem is rendered based on the GridView definition, so there is no real concept of column numbers. What you do is bind objects to the the listview's itemsource and it creates listviewitems from it. Thus, there are a few hoops to jump through.
This link has an example of how to do some simple object data binding. The advantage of this is what binding structure you have for design time can probably be reused for run-time if you set the datacontext/itemsource to an empty object instead of the static one in XAML.
If you're doing this to show examples or you just have a static data source that you want to use, I would recommend using the XmlDataProvider. Then you'd change your ListView to be like this,
<ListView IsSynchronizedWithCurrentItem="True" Margin="8,68,304,188"
BorderThickness="2,2,2,2">
<ListView.View>
<GridView>
<GridViewColumn Width="150" Header="Column1" DisplayMemberPath="{Binding XPath=/A/B}"/>
<GridViewColumn Width="150" Header="Column2" DisplayMemberPath="{Binding XPath=/A/C"/>
</GridView>
</ListView.View>
<ListViewItem>
</ListViewItem>
</ListView>