Windows Vista Forums
Vista Forums Home Join Vista Forums Windows 7 Forum Vista Tutorials Tags
Welcome to Windows Vista Forums. Our forum is dedicated to helping you find solutions with any problems, errors or issues you are experiencing with Windows Vista. The Vista forum also covers news and updates and has an extensive Windows Vista tutorial section that covers a wide range of tips and tricks.

Go Back   Vista Forums > Misc Newsgroups > Avalon

Vista - appyling styles to a GridViewColumn

 
 
Old 02-10-2006   #1 (permalink)
Jason Dolinger


 
 

appyling styles to a GridViewColumn

Hi all,

Hopefully this is an easy question... How can you apply a style to a
GridViewColumn that is displaying tabular data in a ListView? All I'd
really like to do right now is give the text in each cell a center
horizontal alignment, and I may need to be able to programatically
change the Opacity of various rows in the ListView at runtime.

I'm binding each column to a different property of each object (that is
of course in an ObservableCollection<T>)using the
GridViewColumn.DisplayMemberPath property. The SDK docs state:

"Styling for individual column cells can be defined by specifying one or
more DataTemplate controls and specifying them by using the CellTemplate
or CellTemplateSelector properties."

A couple things confuse me about this:

1. I want to add a Style, not a DataTemplate. I'm not trying to create
a visual here for an element which doesn't have one yet (because the
ListView seems to display my data just fine). All I want to do is style
the cells TextAlignment, etc...
2. CellTemplate is a Property on GridViewColumn. That to me implies
that you are applying the Template to all cells in the Column, but the
documentation states that this is for styling individual cells.
3. Later on, the documentation says,"If the DisplayMemberPath property
is set for a column, do not set the CellTemplate or CellTemplateSelector
properties on that column." What do these properties have to do with
one another? CellTemplate would seem to be attempting to style a cell,
while DisplayMemberPath is just telling the row which member of your
object it's going to bind into that column.

Lastly, is there any way to get a handle on a particular row in the
ListBox? For example to intercept MouseEnter or MouseLeave events, or
apply a style to all cells in a row, rather than a column?


Thanks, this control seems very promising to me (I've been trying to
roll my own grid and I didn't know about GridView until today. Why oh
why doesn't Mr. Sells mention it in his book?). However I'm still
trying to figure out whether it can support what I'm doing.

Thanks,
Jason

My System SpecsSystem Spec
Old 02-10-2006   #2 (permalink)
Drew Marsh


 
 

Re: appyling styles to a GridViewColumn

Jason Dolinger wrote:

> A couple things confuse me about this:
>
> 1. I want to add a Style, not a DataTemplate. I'm not trying to
> create
> a visual here for an element which doesn't have one yet (because the
> ListView seems to display my data just fine). All I want to do is
> style
> the cells TextAlignment, etc...


You can't just add style. The reason it's rendering anything is because it
has a default "look" which basically just renders a TextBlock. If you want
to change anything about the rendering you must supply a whole template.

> 2. CellTemplate is a Property on GridViewColumn. That to me implies
> that you are applying the Template to all cells in the Column, but the
> documentation states that this is for styling individual cells.


It's *per* column. If you have six columns of data, you can give each one
of them a different template.

> 3. Later on, the documentation says,"If the DisplayMemberPath
> property
> is set for a column, do not set the CellTemplate or
> CellTemplateSelector
> properties on that column." What do these properties have to do with
> one another?
> CellTemplate would seem to be attempting to style a
> cell,
> while DisplayMemberPath is just telling the row which member of your
> object it's going to bind into that column.


Using DisplayMemberPath, you're basically telling the GridViewColumn to use
a built in style which is that TextBlock I mentioned. Whatever you specify
for DisplayMemberPath is what ends up going into the Binding for the TextBlock.
Using DisplayMemberPath is the easy approach, but you cannot control the
style this way.

> Lastly, is there any way to get a handle on a particular row in the
> ListBox? For example to intercept MouseEnter or MouseLeave events, or
> apply a style to all cells in a row, rather than a column?


Have a look at GridViewRowPresenter[1].

For more information on GridView, I highly recommend reading this section[1]
of the SDK.

HTH,
Drew

[1] http://windowssdk.msdn.microsoft.com...wPresenter.asp
[2] http://windowssdk.msdn.microsoft.com...972d8749d9.asp

___________________________________
Drew Marsh
Chief Software Architect
Mimeo.com, Inc. - http://www.mimeo.com
Microsoft C# / WPF MVP
Weblog - http://blog.hackedbrain.com/


My System SpecsSystem Spec
Old 02-11-2006   #3 (permalink)
Jason Dolinger


 
 

Re: appyling styles to a GridViewColumn

Drew Marsh wrote:
> Jason Dolinger wrote:
>
>> A couple things confuse me about this:
>>
>> 1. I want to add a Style, not a DataTemplate. I'm not trying to
>> create
>> a visual here for an element which doesn't have one yet (because the
>> ListView seems to display my data just fine). All I want to do is
>> style
>> the cells TextAlignment, etc...

>
>
> You can't just add style. The reason it's rendering anything is because
> it has a default "look" which basically just renders a TextBlock. If you
> want to change anything about the rendering you must supply a whole
> template.
>
>> 2. CellTemplate is a Property on GridViewColumn. That to me implies
>> that you are applying the Template to all cells in the Column, but the
>> documentation states that this is for styling individual cells.

>
>
> It's *per* column. If you have six columns of data, you can give each
> one of them a different template.
>
>> 3. Later on, the documentation says,"If the DisplayMemberPath
>> property
>> is set for a column, do not set the CellTemplate or
>> CellTemplateSelector
>> properties on that column." What do these properties have to do with
>> one another? CellTemplate would seem to be attempting to style a
>> cell,
>> while DisplayMemberPath is just telling the row which member of your
>> object it's going to bind into that column.

>
>
> Using DisplayMemberPath, you're basically telling the GridViewColumn to
> use a built in style which is that TextBlock I mentioned. Whatever you
> specify for DisplayMemberPath is what ends up going into the Binding for
> the TextBlock. Using DisplayMemberPath is the easy approach, but you
> cannot control the style this way.
>
>> Lastly, is there any way to get a handle on a particular row in the
>> ListBox? For example to intercept MouseEnter or MouseLeave events, or
>> apply a style to all cells in a row, rather than a column?

>
>
> Have a look at GridViewRowPresenter[1].
>
> For more information on GridView, I highly recommend reading this
> section[1] of the SDK.
>
> HTH,
> Drew
>
> [1]
> http://windowssdk.msdn.microsoft.com...wPresenter.asp
>
> [2]
> http://windowssdk.msdn.microsoft.com...972d8749d9.asp
>
>
> ___________________________________
> Drew Marsh
> Chief Software Architect
> Mimeo.com, Inc. - http://www.mimeo.com
> Microsoft C# / WPF MVP
> Weblog - http://blog.hackedbrain.com/
>
>


Thanks Drew. Seems the gist of it is that I'll just have to use a
DataTemplate containing a TextBlock which will replace the stock
TextBlock that came with GridViewColumn. However, do you have any
suggestions for being able to databind each column to a different
property or your object? Previously, I just set the DisplayMemberPath
for each column. Now do I need to create a different DataTemplate for
each column simply to bind the TextBlock to a different property? I can
create my own DataTemplate class which contains all of the common layout
that I need and then programmatically set the binding for the TextBlock
to different properties. But it there a more elegant way?

Thanks,
Jason
My System SpecsSystem Spec
Old 02-11-2006   #4 (permalink)
Michael Latta


 
 

Re: appyling styles to a GridViewColumn

If you assign a custom template to a column, you need to find out what is
set as the data context for that template. If the template applies to the
object for that row (as would seem logical), then you can do binding within
your template very easily:

<DataTemplate DataType="...">
<DataTemplate.VisualTree>
<TextBlock Text="{Binding Path=yourColumnPath}"/>
</DataTemplate.VisualTree>
</DataTemplate/>

You may need to play with the RelativeSource property of the binding if the
data context is not quite what you want.

Michael




"Jason Dolinger" <jdolinger@lab49.com> wrote in message
news:OncXqrlLGHA.1532@TK2MSFTNGP12.phx.gbl...
> Drew Marsh wrote:
>> Jason Dolinger wrote:
>>
>>> A couple things confuse me about this:
>>>
>>> 1. I want to add a Style, not a DataTemplate. I'm not trying to
>>> create
>>> a visual here for an element which doesn't have one yet (because the
>>> ListView seems to display my data just fine). All I want to do is
>>> style
>>> the cells TextAlignment, etc...

>>
>>
>> You can't just add style. The reason it's rendering anything is because
>> it has a default "look" which basically just renders a TextBlock. If you
>> want to change anything about the rendering you must supply a whole
>> template.
>>
>>> 2. CellTemplate is a Property on GridViewColumn. That to me implies
>>> that you are applying the Template to all cells in the Column, but the
>>> documentation states that this is for styling individual cells.

>>
>>
>> It's *per* column. If you have six columns of data, you can give each one
>> of them a different template.
>>
>>> 3. Later on, the documentation says,"If the DisplayMemberPath
>>> property
>>> is set for a column, do not set the CellTemplate or
>>> CellTemplateSelector
>>> properties on that column." What do these properties have to do with
>>> one another? CellTemplate would seem to be attempting to style a
>>> cell,
>>> while DisplayMemberPath is just telling the row which member of your
>>> object it's going to bind into that column.

>>
>>
>> Using DisplayMemberPath, you're basically telling the GridViewColumn to
>> use a built in style which is that TextBlock I mentioned. Whatever you
>> specify for DisplayMemberPath is what ends up going into the Binding for
>> the TextBlock. Using DisplayMemberPath is the easy approach, but you
>> cannot control the style this way.
>>
>>> Lastly, is there any way to get a handle on a particular row in the
>>> ListBox? For example to intercept MouseEnter or MouseLeave events, or
>>> apply a style to all cells in a row, rather than a column?

>>
>>
>> Have a look at GridViewRowPresenter[1].
>>
>> For more information on GridView, I highly recommend reading this
>> section[1] of the SDK.
>>
>> HTH,
>> Drew
>>
>> [1]
>> http://windowssdk.msdn.microsoft.com...wPresenter.asp
>> [2]
>> http://windowssdk.msdn.microsoft.com...972d8749d9.asp
>> ___________________________________
>> Drew Marsh
>> Chief Software Architect
>> Mimeo.com, Inc. - http://www.mimeo.com
>> Microsoft C# / WPF MVP
>> Weblog - http://blog.hackedbrain.com/
>>
>>

>
> Thanks Drew. Seems the gist of it is that I'll just have to use a
> DataTemplate containing a TextBlock which will replace the stock TextBlock
> that came with GridViewColumn. However, do you have any suggestions for
> being able to databind each column to a different property or your object?
> Previously, I just set the DisplayMemberPath for each column. Now do I
> need to create a different DataTemplate for each column simply to bind the
> TextBlock to a different property? I can create my own DataTemplate class
> which contains all of the common layout that I need and then
> programmatically set the binding for the TextBlock to different
> properties. But it there a more elegant way?
>
> Thanks,
> Jason



My System SpecsSystem Spec
Old 02-11-2006   #5 (permalink)
Jason Dolinger


 
 

Re: appyling styles to a GridViewColumn

Michael Latta wrote:
> If you assign a custom template to a column, you need to find out what is
> set as the data context for that template. If the template applies to the
> object for that row (as would seem logical), then you can do binding within
> your template very easily:
>
> <DataTemplate DataType="...">
> <DataTemplate.VisualTree>
> <TextBlock Text="{Binding Path=yourColumnPath}"/>
> </DataTemplate.VisualTree>
> </DataTemplate/>
>
> You may need to play with the RelativeSource property of the binding if the
> data context is not quite what you want.
>
> Michael
>
>
>


Thanks Michael. I was looking at something like that. The problem is
that I need to do this in C#, not XAML. I'm basically trying to build a
generic grid which binds to any ObservableCollection<T> and build rows
and columns for type T. I'm using reflection to get the public
properties of T and building columns for each one. This works easily
enough when using the display member path:

// all of this going in a ListView:
Type t = T.GetType();
PropertyInfo[] propertyDescriptors = t.GetProperties();
GridView view = new GridView();

for (int i = 0; i < gridTypeProperties.Length; i++)
{
GridViewColumn column = new GridViewColumn();
string propName = propertyDescriptors[i].Name;
column.header = propName;
column.DisplayMemberPath = propName; // binds column to this property
of the object

view.Columns.Add(column);

}


But when trying to build a DataTemplate instead in C#, I'm not exactly
sure how to proceed. Something like this would make sense:

public class GridCellDataTemplate : DataTemplate
{
public GridCellDataTemplate(string propName)
{
FrameworkElementFactory contentFact = new
FrameworkElementFactory();
contentFact.Type = typeof(TextBlock);

TemplateBindingExtension tb = new
TemplateBindingExtension(TextBlock.TextProperty);
contentFact.SetValue(propName, tb); //does not compile
of course!
this.VisualTree = contentFact;
}
}
}



and then:

Type t = T.GetType();
PropertyInfo[] propertyDescriptors = t.GetProperties();
GridView view = new GridView();

for (int i = 0; i < gridTypeProperties.Length; i++)
{
GridViewColumn column = new GridViewColumn();
string propName = propertyDescriptors[i].Name;
column.header = propName;
column.CellTemplate = new GridCellDataTemplate(propName);
view.Columns.Add(column);

}


But the TemplateBindingExtension won't let me bind a portion of the
visual tree that would be created by the FrameworkElementFactory to a
simple CLR property. It only accepts Dependency properties (and no, the
properties on my model objects are not DPs).

Is there some way to make this work? Any help is appreciated as always!

Thanks,
Jason











My System SpecsSystem Spec
Old 02-11-2006   #6 (permalink)
Jason Dolinger


 
 

Re: appyling styles to a GridViewColumn

Drew Marsh wrote:
> Jason Dolinger wrote:
>


>
>> Lastly, is there any way to get a handle on a particular row in the
>> ListBox? For example to intercept MouseEnter or MouseLeave events, or
>> apply a style to all cells in a row, rather than a column?

>
>
> Have a look at GridViewRowPresenter[1].
>
> For more information on GridView, I highly recommend reading this
> section[1] of the SDK.
>
> HTH,
> Drew
>
> [1]
> http://windowssdk.msdn.microsoft.com...wPresenter.asp
>
> [2]
> http://windowssdk.msdn.microsoft.com...972d8749d9.asp
>
>
> ___________________________________
> Drew Marsh
> Chief Software Architect
> Mimeo.com, Inc. - http://www.mimeo.com
> Microsoft C# / WPF MVP
> Weblog - http://blog.hackedbrain.com/
>
>


Drew, I've been looking at those links and trying to understand how to
manipulate the GridViewRowPresenter. I can see that they are in my
visual tree when the table renders. This is snip from the output of a
program I wrote to print out the visual tree of a Visual:

Visual Type: System.Windows.Controls.Border, Name:
Visual Type:
System.Windows.Controls.ScrollContentPresenter, Name:
Visual Type: System.Windows.Controls.ItemsPresenter, Name:
Visual Type:
System.Windows.Controls.VirtualizingStackPanel, Name:
Visual Type: System.Windows.Controls.ListViewItem, Name:
Visual Type: System.Windows.Controls.Border, Name:
Visual Type:
System.Windows.Controls.GridViewRowPresenter, Name:
Visual Type:
System.Windows.Controls.ContentPresenter, Name:
Visual Type: System.Windows.Controls.TextBlock, Name:
Visual Type:
System.Windows.Controls.ContentPresenter, Name:
Visual Type: System.Windows.Controls.TextBlock, Name:
Visual Type:
System.Windows.Controls.ContentPresenter, Name:

etc...


So basically I want to register some event handlers for the MouseEnter
and MouseLeave events for each GridViewRowPresenter. However, I don't
really want to have to dig into the visual tree to get these items. I
would think that ListBox would have something on it's API that would
give you access to the collection of GridViewRowPresenters, but there
doesn't seem to be.

Even that doesn't take it far enough, because I don't really want to
register the event handlers on the already existing
GridViewRowPresenter. I really want to be able to have whatever factory
the framework uses to create the GridViewRowPresenter know to register
some handlers with those events. I dug into the ListBox.ItemsPanel at
runtime. It's VisualTree property is a FrameworkElementFactory which
has a Type of VirtualizingStackPanel. However, the other members all
seem to be null (like NextSibling). So I'm not sure how to dig deeper
in to find the FrameworkElementFactory for the GridViewRowPresenter.

Any tips on this?

Thanks!
Jason
My System SpecsSystem Spec
Old 02-11-2006   #7 (permalink)
Jason Dolinger


 
 

Re: appyling styles to a GridViewColumn

Michael Latta wrote:
> You can register for collection change events on the ListView Items
> collection for changes in the logical tree. For changes in the visual tree
> I do not see equivalent events. The Children property unfortunately does
> not implement ICollectionChangeNotify. As a last resort you could always
> use LayoutUpdated to trigger revisiting all the children of the virtualizing
> panel.
>
> Michael
>


Hey Michael, I'm not looking for actual changes to the Visual Tree. I
just want to detect that the user has moused over a certain row or that
the mouse has left that row.

Thanks,
Jason
My System SpecsSystem Spec
Old 02-11-2006   #8 (permalink)
Jason Dolinger


 
 

Re: appyling styles to a GridViewColumn

Drew Marsh wrote:
> Jason Dolinger wrote:
>
>> So basically I want to register some event handlers for the MouseEnter
>> and MouseLeave events for each GridViewRowPresenter. However, I don't
>> really want to have to dig into the visual tree to get these items. I
>> would think that ListBox would have something on it's API that would
>> give you access to the collection of GridViewRowPresenters, but there
>> doesn't seem to be.
>>
>> Even that doesn't take it far enough, because I don't really want to
>> register the event handlers on the already existing
>> GridViewRowPresenter. I really want to be able to have whatever
>> factory the framework uses to create the GridViewRowPresenter know to
>> register some handlers with those events. I dug into the
>> ListBox.ItemsPanel at runtime. It's VisualTree property is a
>> FrameworkElementFactory which has a Type of VirtualizingStackPanel.
>> However, the other members all seem to be null (like NextSibling). So
>> I'm not sure how to dig deeper in to find the FrameworkElementFactory
>> for the GridViewRowPresenter.
>>
>> Any tips on this?

>
>
> Well, I was going to suggest you simply use event routing by handling
> the MouseEnter/MouseLeave routed event on the ListView itself (since it
> bubbles) and then just detecting if the source element was
> GridViewRowPresenter and do whatever you like in response. Unfortunately
> the events aren't bubbling up in my test case so I don't know what's
> going wrong.
>
> Still trying....
>
> -Drew
>
> ___________________________________
> Drew Marsh
> Chief Software Architect
> Mimeo.com, Inc. - http://www.mimeo.com
> Microsoft C# / WPF MVP
> Weblog - http://blog.hackedbrain.com/
>
>


Do MouseEnter/MouseLeave events bubble (I'm at home without my trusty
copy of Programming Windows Presentation Foundation). It wouldn't seem
to make sense to me. I would think that MouseEnter and MouseLeave would
only fire upon the mouse entering or leaving the entire ListView itself.
My System SpecsSystem Spec
Old 02-16-2006   #9 (permalink)
Jason Dolinger


 
 

Re: appyling styles to a GridViewColumn

Drew Marsh wrote:
> Jason Dolinger wrote:
>
>> Do MouseEnter/MouseLeave events bubble (I'm at home without my trusty
>> copy of Programming Windows Presentation Foundation). It wouldn't
>> seem to make sense to me. I would think that MouseEnter and
>> MouseLeave would only fire upon the mouse entering or leaving the
>> entire ListView itself.

>
>
> From the SDK[1]:
>
> <snip>
> Remarks
> This is a bubbling event.
> </snip>
>
> Why shouldn't they tunnel/bubble? They do in DOM level 2 events[2]
> (called mouseover, mouseout there) as well btw.
>
> Anywho, I still wasn't getting the event which makes me wonder exactly
> what's going on there. I thought maybe something was swallowing it, so
> I registered manually with AddHandler with handledEventsToo = true and
> still got nada. Innnnnteresting.... and irritating.
>
> Cheers,
> Drew
>
> [1]
> http://windowssdk.msdn.microsoft.com...enterevent.asp
>
> [2]
> http://www.w3.org/TR/2000/REC-DOM-Le...nts-MouseEvent
>
> ___________________________________
> Drew Marsh
> Chief Software Architect
> Mimeo.com, Inc. - http://www.mimeo.com
> Microsoft C# / WPF MVP
> Weblog - http://blog.hackedbrain.com/
>
>


Drew, Ji Zhang came up with the answer to the problem in a thread marked
Problem with behaviour of MouseEvents on ListViewItems. The magic
solution is simply to create a typed style for ListViewItem:

<Style TargetType='{x:Type ListViewItem}' >
<EventSetter Event='MouseDown' Handler='HandleMouseDown'/>
<EventSetter Event='MouseUp' Handler='HandleMouseUp'/>
......
</Style>

<ListView ItemContainerStyle="{StaticResource}"/>

Phew, on the next thing...
My System SpecsSystem Spec
Old 02-21-2006   #10 (permalink)
Ji Zhang [MSFT]


 
 

Re: appyling styles to a GridViewColumn

These events should be bubbling up. I just wonder why in your sample it does
not work. Could you post your code here? I'd like to help you.

"Drew Marsh" wrote:

> Jason Dolinger wrote:
>
> > Drew, Ji Zhang came up with the answer to the problem in a thread
> > marked
> > Problem with behaviour of MouseEvents on ListViewItems. The magic
> > solution is simply to create a typed style for ListViewItem:
> > <Style TargetType='{x:Type ListViewItem}' >
> > <EventSetter Event='MouseDown'
> > Handler='HandleMouseDown'/>
> > <EventSetter Event='MouseUp' Handler='HandleMouseUp'/>
> > ......
> > </Style>
> > <ListView ItemContainerStyle="{StaticResource}"/>
> >
> > Phew, on the next thing...

>
> Yeah I saw that, thanks for posting it here too though.
>
> I still find it odd that these events are not bubbling up the way they should
> and would personally consider this a bug. There's no reason you should have
> to attach a handler to each element that way, it flies in the face of the
> concept of routed events. Maybe someone from MS will comment, otherwise I'll
> go ahead and post a bug.
>
> Cheers,
> Drew
>
> ___________________________________
> Drew Marsh
> Chief Software Architect
> Mimeo.com, Inc. - http://www.mimeo.com
> Microsoft C# / WPF MVP
> Weblog - http://blog.hackedbrain.com/
>
>
>

My System SpecsSystem Spec
 

Thread Tools


Similar Threads
Thread Forum
Templates/Styles .NET General
Visual Styles Vista General
DVD Maker Menu Styles... Vista music pictures video


Vista Forums is an independent web site and has not been authorized,
sponsored, or otherwise approved by Microsoft Corporation.
"Windows Vista", the Start Orb, and related materials are trademarks of Microsoft Corp.
© Designer Media Ltd

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46