Bring closer Items in ItemsControl - wpf

I have an Itemscontrol, witch contains two items after the Binding.
My problem is that the second item is getting out from the window's area.
My question is -
how can I bring closer the Items's texts without reducing the font size or increasing the window's height ?
Is there something like the padding and marging of HTML ? or maybe some other trick?
p.s - the font size and the height of the window must not be changed.
This is how it looks:
(source: timg.co.il)
And this is the code:
<UserControl x:Class="WpfApplication4.AnnouncmentsControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="86" Width="300">
<Grid>
<ItemsControl Name="announcmentsListBox" ItemsSource="{Binding}">
</ItemsControl>
</Grid>

Your TextBlock has a height set of 40 units. If you remove that attribute altogether, you'll see the items spaced more naturally.
So your XAML would look more like this:
<Grid>
<ItemsControl Name="announcmentsListBox" ItemsSource="{Binding}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Path=Text}" />
<Button />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>

I would advise you to use Mole visualizer to examine the generated items. Mole 4.2 can be downloaded from http://karlshifflett.wordpress.com/mole-for-visual-studio/
Just need to copy "Mole.Visualizer.dll" to appropriate visualizer folder.
If you are developing on Vista and are
running with Elevated Security
enabled, you must install Mole in the
following directory.
* {VS Install path}\Common7\Packages\Debugger\Visualizers
All others download and unzip the
above package. Copy the file in the
Release package to either:
* My Documents\Visual Studio 2005\Visualizers {VS2005}
* My Documents\Visual Studio 2008\Visualizers {VS2008}
You can set a break point somewhere in the code which is easily accessible and then start the Mole visualizer on some object. Navigate the visual tree to the itemscontrol. Look for values in Margin and Padding for the generated TextBlocks. It will also tell you whether the values are inherited or local etc.

Use a Padding set to 0. Also, you can set Negative Margins which in many cases is the only way to coerce text into certain layouts (where Padding doesn't fit the bill, and container layout is non-overridable.)
You can also implement your own items panel template and redefine the layout of each item to compensate for the the padding being introduced, but this shouldn't be necessary. It would, however, afford you control over layout calculation for all items so that you can best-fit each item (and even go one step further and implement crazy new item layouts such as a carousel, as has been demoed by many pre-RTM videos of WPF/Avalon.)
Hope that helps, it's what I do.

Related

Create/Modify new WPF UI components

I want to change the graphical UI elements in WPF.
For example, I want to use a kind of a stack panel, but on the other hand I want to show my details in a star, or circle, etc.
Maybe setting a bitmap as a background, but I am working with lots of Data using zoom tool.
I found tutorials, documentation only for changing attributes of "old components", but nothing to make new ones.
Great resource for WPF beginners is www.wpftutorial.net
One of the best idea of WPF is separation of concerns:
UI Control = Logic in Code/XAML + Template
Using templates in XAML we can vary representation without modifying the control.
For example, if there is a need in creation of list of items. Then we can use ListBox control:
<ListBox>
<ListBoxItem>USA</ListBoxItem>
<ListBoxItem>UK</ListBoxItem>
</ListBox>
By default LisboxItem internal part is just binded TextBlock.
Now making UI modification without changing control source code:
<ListBox ImageSource="{Binding PathToSource}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Source="{StaticResource ProjectIcon}"/>
<TextBlock Text="{Binding Path=PropertyName}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
there appears image and text.
If there is a need in creating exclusive control then you can always use Custom Control.
Using raster images (e.g. PNG) is not good point, especially with zoom behaviour. If it is possible better to use vector images, that can be created in XAML or imported from SVG.

TextTrimming in panel in ScrollViewer

I am trying to set up an element within a WPF application, but cannot get the TextTrimming on the TextBlocks to work properly. This is within a ScrollViewer. I am currently using a DockPanel as the inner container.
I have searched quite a bit, but found no questions addressing this issue.
The XAML for the container:
<Grid>
<ScrollViewer>
<DockPanel Name="listedCharacters" LastChildFill="False"></DockPanel>
</ScrollViewer>
</Grid>
The XAML for the child elements (added by code):
<UserControl …>
<Grid DockPanel.Dock="Top" HorizontalAlignment="Stretch">
<TextBlock Text="{Binding FullName}" TextTrimming="CharacterEllipsis" />
</Grid>
</UserControl>
The first problem is that whether I use the DockPanel or a StackPanel, as the inner container, the child element's width appears to be dictated by its content (the TextBlocks) rather than constrained by the parent ScrollViewer.
The effect I want is for the ellipsis to truncate each TextBlock's content when the Window's grid column (not shown in code) is narrower than the bound text. Basically, a list that scrolls vertically when needed, and trims horizontally (which I thought would have been sufficiently common that the answer would be out there; alas, no).
I believe I need to use my own UserControl for this, as there is a lot more going on than shown her; right-click menus on the item in the list, etc.
The secondary issue, iff the optimal panel to use is the DockPanel, how to apply the DockPanel.Dock="Top" through code (C#) when the elements are dynamically added? Again, I cannot find anything that appears to explain this. (I know it is probably in the wrong place in the sample code above.)

Skinning Control Backgrounds - Better Performance?

sorry if this question is overly simple, but I'm having a hard time figuring out how to create backgrounds to controls - in the hopes that it will improve app performance.
I have 9 different controls. All of them have a background. The backgrounds are made up of either images, other controls or both. All of those backgrounds have another background.
Think of this like Power Point with slides, slide layouts and slide masters - inherited in that order. I have 9 slides / controls.
The first 3 controls have the same "control layout" (let's call it
ControlLayout1). ControlLayout1 gets some of it's elements from ControlMaster1.
The second 3 controls also have the same control layout, but it is
different from the first. Let's call it ControlLayout2. It also
inherits from ControlMaster1.
The final set of 3 controls are different again. We can call them
ControlLayout3. But this time, they inherit from a different master - ControlMaster2.
Right now in each control I'm writing out all the XAML each time separately. I'm thinking there must be a way to not write these in each of these each item. Ideally, what I would like to create is one set of XAML that can be reused.
Here's some pseudo-XAML:
<UserControl x:Name="Control1">
<MyBackground (ControlLayout1)/>
</UserControl>
<UserControl x:Name="Control2">
<MyBackground (ControlLayout2)/>
</UserControl>
<UserControl x:Name="Control3">
<MyBackground (ControlLayout3)/>
</UserControl>
And then somewhere for ControlLayouts (I don't know, like Application.Resources or elsewhere)
<Canvas x:Name="ControlLayout1">
<MyMasterBackground (ControlMaster1)/>
</Canvas>
<Canvas x:Name="ControlLayout2">
<MyMasterBackground (ControlMaster1)/>
<TextBox Text="The Control 2">
</Canvas>
<Canvas x:Name="ControlLayout3">
<MyMasterBackground (ControlMaster2)/>
<TextBox Text="The Control 3">
</Canvas>
And then for the ControlMasters
<Canvas x:Name="ControlMaster1">
<Canvas.Background>
<ImageBrush ImageSource="/Images/image1.jpg" />
</Canvas.Background>
</Canvas>
<Canvas x:Name="ControlMaster2">
<Canvas.Background>
<ImageBrush ImageSource="/Images/image2.jpg" />
</Canvas.Background>
<TextBox Text="Control Master 1">
</Canvas>
Once defined, the ControlLayouts and ControlMasters never need to change - they are static.
Beyond just having a smaller XAP if I can put these all in one location and reuse the XAML, I'm hoping performance will be improved in my app as the ControlLayouts automatically get BitmapCached or something like that.
So first, is there a good strategy to implement the above (the ControlLayouts and Masters do not have any code-behind)? Secondly will performance be improved in loading of Control1, Control2, etc.? Finally, if they were pure usercontrols (i.e. they had some code behind), would that be better for performance?
Thanks in advance!
What you ask for is a combination of a few things:
About the Background thing: just create a dependency property (let's call it MyBackgroundDP) of type Brush in the code behind of a UserControl, and bind it to your XAML like:
<UserControl ...>
<Grid Background={"Binding MyBackgroundDP, RelativeSource={RelativeSource Mode=FindAncestor, AncestoryType=UserControl}}">
<!-- More XAML declarations -->
</Grid>
</UserControl>
To create the dependency property, you can use the built in snippet in visual studio: propdp
Simply write "propdp" and that TAB twice. Fill up the fields and it's all good.
Alright so that was easy enough, right? ;)
Now the tougher part: making so-called master pages.
Actually it's not that much different from the background thing.
Declare another dependency property, only this time of type object, or FrameworkElement (better).
Then in your XAML, you declare a kind of placeholder: ContentControl. Let's call it MyContentDP for this example:
<UserControl ...>
<Grid Background={"Binding MyBackgroundDP, RelativeSource={RelativeSource Mode=FindAncestor, AncestoryType=UserControl}}">
<ContentControl ContentTemplate="{Binding MyContentDP, RelativeSource={RelativeSource Mode=FindAncestor, AncestoryType=UserControl}}" />
</Grid>
</UserControl>
You can then fine tune whatever else you want to provide in this "master view", add a border around the Grid, put some flowers, you name it.
Once you're done, this is how you use it, assuming it was called MyUserControl
<Window ...
xmlns:local="...reference_to_your_usercontrol_dll/exe">
<Grid>
<local:MyUserControl MyBackgroundDP="Red">
<local:MyUserControl.MyContentDP>
<!-- More XAML declarations here -->
</local:MyUserControl.MyContentDP>
</local:MyUserControl>
</Grid>
</Window>
Now the performance point:
If you put all the XAML for this as a Custom control (which is DIFFERENT from a UserControl), you can then put all the XAML in your App.xaml
Why? because parsing XAML can be an intensive operation, and if you make WP7/SL parse it at runtime whenever you need it, you lose performance.
Instead, your App.xaml gets parsed at startup, then it's in memory. That's what's done in the loading of your application. You would get a performance boost, although it would be minimal for controls made of few XAML, it is still a good practice.
Hope this helps,
Bab.

Is there any free Visual Studio plug-in/extension or external program to visualize XAML DataTemplate?

Visual Studio (10) gives the expected message "Intentionally Left Blank" in the designer.
I know already that I can do this with Blend, just looking around if there is an alternative solution...
I don’t really mind to graphically edit the template; I want only to see it without having to run the application.
Thanks!
Not exactly what you might want, but you can use XamlPad and just paste the content of your datatemplate into it. As long as you don't have layout related bindings, it should work well. Bindings are just ignored by xamlpad, and you need to add the 2 wpf namespace aliases by hand.
for example:
<TextBlock xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Text="{Binding test}"
Background="Red"
Width="20" Height="20"/>
the textblock is empty in XamlPad, but everything else works as expected.

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.

Resources