![]() |
![]() | ![]() | ![]() | ![]() | ![]() | ![]() | ![]() |
| 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. |
| |||||||
| |
| | #1 (permalink) |
| | 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 Specs![]() |
| | #2 (permalink) |
| | 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 Specs![]() |
| | #3 (permalink) |
| | 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 Specs![]() |
| | #4 (permalink) |
| | 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 Specs![]() |
| | #5 (permalink) |
| | 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 Specs![]() |
| | #6 (permalink) |
| | 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 Specs![]() |
| | #7 (permalink) |
| | 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 Specs![]() |
| | #8 (permalink) |
| | 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 Specs![]() |
| | #9 (permalink) |
| | 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 Specs![]() |
| | #10 (permalink) |
| | 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 Specs![]() |
| Thread Tools | |
| |
Similar Threads | ||||
| Thread | Forum | |||
| Templates/Styles | .NET General | |||
| Visual Styles | Vista General | |||
| DVD Maker Menu Styles... | Vista music pictures video | |||