WPF TreeView styled like the Mac NSOutlineView - wpf

I'd like to style my TreeView like the Mac NSOutlineView.
http://s3.amazonaws.com/cocoacontrols_production/osx_screens/44/full.png?1299027729
The key features being:
TreeView full width highlighting of selected item
Background color
Different style for root header items
I believe I can track down 2 and 3, but can't find anything related to number 1.
Seems like I can't really do it, but I'll play around with Blend. Is there no code access to drawing? like here is a box replace the row drawing code? I made a prototype just now in wxPython using AGW's pure python HyperTreeList that looks the same, but unfortunately dragging and dropping has serious graphics/refresh issues.

I have just pushed on Mongoose repository a TreeViewItem Style that does what you need.
You can find it here : StretchedTreeViewItemControlTemplate
Here is a sample code :
<TreeView ItemContainerStyle="{StaticResource StretchedTreeViewItemControlTemplate}">
<TreeViewItem Header="Item 1">
<TreeViewItem Header="Item 1.1">
<TreeViewItem.Style>
<Style BasedOn="{StaticResource StretchedTreeViewItemControlTemplate}" TargetType="{x:Type TreeViewItem}">
<Setter Property="FontSize" Value="15" />
</Style>
</TreeViewItem.Style>
</TreeViewItem>
</TreeViewItem>
<TreeViewItem Header="Item 2" Background="AntiqueWhite" />
</TreeView>

Would ItemsControl.ItemContainerStyle be appropriate ? http://msdn.microsoft.com/fr-fr/library/system.windows.controls.itemscontrol.itemcontainerstyle(v=vs.85).aspx
A quick test under Blend brought the following :
For a parent :
For a children :
Notice that it is uneven, it doesn't look good.
One might ask why not stretching it up to the left border ? I guess this is not possible (from what I've seen on Blend) unless you recreate most of the template of course.
Also this would certainly kill the hierarchical look there is between items if their selector left side would be aligned to the same horizontal value.
Now the other thing is that even though you'd do that (as you requested), the expander triangle would be lost in a mess of blue ... bad UX in my opinion.
In the end your control would look more like a ListBox than a TreeView.
Anyway, here's the procedure (I edited ItemContainerStyleTemplate of a TreeView)
(sorry didn't read well your last comment, in the end my result is pretty much like yours)
Where to do it in Blend :

Related

TextBlock internal margin

I suppose when several TextBlocks are located in a row(i.e in StackPanel with the Horizontal orientation) they should look as if it was one TextBlock. But I found the following:
The first line is a TextBlock displaying "eeee". The second one is a StackPanel containing 4 TextBlocks and each TextBlock contains "e". As you can see from the picture above, the second line is a little bit longer than the first one. It looks like the TextBlocks have some internal margin. But, in my case, I'd like to prevent it.
So, do you know how to do it?
Try setting the Padding and Margin of the TextBlock to zero.
<TextBlock Padding="0" Margin="0" ... />
Since you have multiple textblocks that you are going to want to do this with, you should probable use a Style to do this.
<StackPanel Orientation="Horizontal">
<Style TargetType="TextBlock">
<Setter Property="Padding" Value="0" />
<Setter Property="Margin" Value="0" />
</Style>
...
</StackPanel>
If this doesn't help, then you could start using negative margins:
Margin="-1,0,0,0"
However this introduces brittleness into your code, because the spacing between text depends on the font size and the text displayed. For example, if you change the font size to 13, you will no longer have this problem with five lower case 'e'. Changing the text to uppercase 'E' will result in the same problem, though.
You could try using the clipping properties on the TextBlock or even the rendering affects, but this seems like a lot of work just to get text to adjust a couple of pixels. May I ask why you are trying to get the two text samples to look the same?
Update:
I am doubtful that you can find a good way to make this work the way that you want to. May you should look into using a RichTextBox or creating a custom control.
Here is a good example use of a RichTextBox with text highlight (although it is foreground highlighting).

How to force zero pixel Gap between Consecutive Cells in WPF DataGrid

i am building an application in WPF for a custom need. First i opted for custom controls, but later on figured out that much of what i needed was already implemented in Datagrid Control. However there is one small glitch:
The problem with Datagrid is that it enforces a minimum of 2 pixel gap between two consecutive cells (1 on each side of the Grid Line). Please have a look at the following diagram for clarity:
.
Please note the 2 pixels gap enforced by the Datagrid between the two consecutive cells:
http://img265.imageshack.us/img265/3545/figurem.png
(Stack overflow wouldn't let me add image to my question citing a spam protection policy for new users)
.
This doesn't suit my requirement as i want the content to appear "continuous" (There must not be this gap of 2 pixels; i want the connecting lines to look "connected"). i've tried fidgeting with the GridLinesVisibility, but it didn't help. The DataGrid is hosting a custom control like this:
<DataGrid.Columns>
<DataGridTemplateColumn Width="25" Header="">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ContentControl Content="{Binding Path=MyCustomControl}" Margin="0"></ContentControl>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
....
</DataGrid.Columns>
i have so far tried:
Switching off the GridLine (see result here: http://img263.imageshack.us/img263/8602/figure2j.png)
Setting the margin of the content property to 0.
Searched google and stackoverflow
Consulted some books.
but nothing seems to come up.
Is there a solution to this/some hack or a workaround or would i have to create everything from scratch? i have decent experience with c#, but i am new to WPF.
Please Help.
What you need to do is get at the DataGridCell style for your DataGrid and set its BorderThickness to be 0. It's hard-coded as 1 in the default style, but fortunately it's easy to override this:
<Style TargetType="DataGridCell">
<Setter Property="BorderThickness" Value="0" />
</Style>
I would suggest putting that into the resources of your DataGrid so it only affects that one grid, unless you want it to have a wider scope than that.
<DataGrid>
<DataGrid.Resources>
<Style TargetType="DataGridCell">...</Style>
</DataGrid.Resources>
...
</DataGrid>
There are other places you could put it as well, depending on your precise needs.

Visual 2010 WPF Designer: Styles sometimes shown/not shown?

Ok, I'm pretty new to WPF programming. Now I always run across the following issue so maybe anyone could lighten me up:
In My Window I have a datagrid that I want to style (column should be green). So I create a ressource:
<Window.Resources>
<Style TargetType= "{x:Type DataGridCell}" x:Key="GreenColumns">
<Setter Property="Background" Value="SeaGreen" />
</Style>
</Window.Resources>
Now I have a Column like that:
<DataGridTextColumn Binding="{Binding N}" Header="N" IsReadOnly="True" CellStyle="{StaticResource GreenColumns}">
It is working, no problem at all!
Now all I want is to apply this resourced style via the Designer in VS 2010.
To do that I click on my DatagridTextColumn. Next I click in "CellStyle" (Property view on the left of course) . In this dropdown there is always a style called "Standard" and sometimes there are self-defined styles too, but not very often. In this case I think I should be able to select my style "GreenColumns". Instead it shows Key: GreenColumns preceeded with a yellow exclamation mark symbol.
I don't get it. What's wrong here? What has to be done in order to show a self-defined style in this dropdown?
I've given up on the Visual Studio XAML designer, even in 2010. There seems to be just too many legitimate techniques that it just cannot handle. I'd say learn XAML code and/or Expression Blend.

WPF TreeView: WordWrap

I have this project that displays hierarchical data with huge amounts of text, and I'm transitioning from winforms to wpf, and with winforms treeview not wordwrapping out of the box I really wanna know how to do this in wpf. Is it possible to have Items in the TreeView use word wrapping, out of the box?
I've looped through a fair amount of threads and google results, but none got me any working method. ScrollViewer.HorizontalScrollBarVisibility="false" got me nowhere either.
If its not there, how would one approach the implementation? I'm quite new to wpf, so I'd appreciate a direction to push in.
Oh, and the framework is 3.5.
I think you'd have to bind the width of the root control of the treeview's node template to the actual width of the treeview itself. So something like the following:
<TreeView x:Name="tv">
<TreeView.ItemTemplate>
<DataTemplate TargetType={x:Type TreeViewItem}">
<TextBlock Text="{Binding PropertyToBind}" Width="{Binding ActualWidth, ElementName=tv}" TextWrapping="Wrap"/>
</DataTemplate>
</TreeView.ItemTemplate>
</TreeView>
You should also be able to set the width binding using a relative source, but I can't recall the syntax.
Usually these types of problems are solved by forcibly constraining the element inside of its parent element (even though it should technically already do that). Just an idea. Good luck.

Silverlight 4: ContentTemplate Background Change

I have a Header style for my datagrid custom header. I am using theme for my application. The problem here is the header background of the datagrid is not changing however when I remove the styles, the header background has no problem, it change.
Here's the themes
Here's my sample application, right click the grid and context menu will appear for the list of themes, select the different themes. I have two columns namely, with header style and without header style. See the difference. Thank you for your help.
<Style x:Key="DataGridHeaderStyle" TargetType="primitive:DataGridColumnHeader">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Grid HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding}" Grid.Column="0" HorizontalAlignment="Left" />
<filter:DataGridColumnFilter Grid.Column="1" HorizontalAlignment="Right" />
</Grid>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
Thank you
I did a quick test, and it does not seem to work with either the tag approach or the ImplicitStyleManager attribute approach. This is probably because the style setter is outside the scope and therefore gets applied without a theme.
Suggestion 1: Look at the way that the Jet Pack theme handles it with resource dictionaries in App.xaml, and try to do something similar. (You will need the theme.xaml file for this. EDIT: This link might help.) If you want to change the theme dynamically, then consider this (old) post about swapping themes in resource dictionaries (I haven't tried it, but it should work).
Suggestion 2: You need to think about style inheritance. Since "BasedOn" needs an x:Key tag, you could instead copy the theme's implicit DataGridColumnHeader style and only modify the parts you are interested in. (I don't know if there's a more elegant way.)
If this is not what you meant, then please provide more sample code.
EDIT [2010-12-09]:
I looked at the code, and I believe the root of the problem is the absence of style inheritance. Your "DataGridHeaderStyle" is saying "Do not use the normal DataGridColumnHeader style, but instead use this TextBlock inside this Grid." So Silverlight does just that: it gives you a styled TextBlock in an unstyled default DataGridColumnHeader.
Proof: Update your "Home.xaml" and add a TextBox in the second column of your "DataGridHeaderStyle" style, next to the current TextBlock. Notice how the theme for the TextBox in the header is changing every time you change the theme (look at the TextBox backgroud), but the background of the column header is stuck on the default colour. Like I said, your custom style is telling Silverlight to ignore the implicit style.
FIX: I do not know how to inherit from implicit styles without an "x:Key" attribute. I googled quite a bit but could not find anything helpful. You will either have to a) create a custom column definition style for all your datagrid headers, or you will have to b) bother the Silverlight team for a new feature in the next version of Silverlight. Or c) pick one theme to stick with and edit a copy of the theme's implicit column header style as your new "DataGridHeaderStyle" style.
My holiday is about to start, so I hope this helped. At least now you know where the problem lies.

Resources