How can I make a Button with multiple content values? - wpf

My goal is to make a Button that has two Content values.
Imagine a Scrabble tile as a button: it has the large letter in the center and a small number in the lower right. This is the effect I am going for.
I made a button that has two ContentPresenter objects in it, and I have given each of the ContentPresenters a different style. However, I have not found a way to give each of the presenters a separate value (ie, if I set the Content of the button to "X" then both ContentPresenters show "X", albeit in different styles).
How can I achieve my objective? I'm guessing my approach is completely wrong....

Bah... I think I know what to do now. I should be making my own control rather than modifying a Button. This would have been obvious to me had I been working in WinForms, but for some reason all this Xaml is making me stupid.

Take a look at the Expander sample ControlTemplate at http://msdn.microsoft.com/en-us/library/ms753296.aspx
Expander is a subclass of HeaderedContentControl, it has two "contents": Header and Content
The control template has two ContentPresenter elements, the ContentPresenter that is not bound to the default content property is defined as:
<ContentPresenter ContentSource="Header" />
If you need to use a Button and you don't want to add another property for the second content you can use an attached property and data bind the second ContentPresnter Content property to it.

I delaled with creating UserControl with multiple 'content slots' here - it's better than deriving from HeaderedControl as you aren't limited in the number of slots.
Sample usage:
<Window x:Class="TkMVVMContainersSample.Services.TaskEditDialog.ItemEditView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Common="clr-namespace:TkMVVMContainersSample.Views.Common"
Title="ItemEditView"
>
<Common:DialogControl>
<Common:DialogControl.Heading>
<!-- Heading string goes here -->
</Common:DialogControl.Heading>
<Common:DialogControl.Control>
<!-- Concrete dialog's content goes here -->
</Common:DialogControl.Control>
<Common:DialogControl.Buttons>
<!-- Concrete dialog's buttons go here -->
</Common:DialogControl.Buttons>
</Common:DialogControl>
</Window>

Related

What do you call a UI element which expands an area of fields in a window?

I am trying to make UI element which expands/collapses an area of fields in a window. I need it specifically for a WPF project.
As an example take the element in the link below.
https://i.stack.imgur.com/MDgNl.png
Pushing the down button expands the area to include more fields as in the example below
https://i.stack.imgur.com/jN6bO.png
Does this kind of UI element have a name? I don't really know what to google to see whether it has been done before.
I think you are looking for the Expander control:
<Expander>
<Grid>
<TextBlock>put your controls to be expanded/collapsed here...</TextBlock>
</Grid>
</Expander>

WPF Howto create a reusable composite component with configurable content?

I would like to create a component that is made up of an arbitrary control and a little button beside this control (same as in this example: http://putridparrot.com/blog/wpf-composite-control/).
My problem is that the content element (the one beside the button) does not always have to be a TextBox, it can be any kind of control. Is there a way to create a component that provides the button, and for which the content element can be freely chosen at design- or even run-time?
You can replace the textbox by a stackpanel, and then in code behind add the children with the controls you want.
ex:
In the XAML:
<stackpanel name="testPanel" Grid.Column="0" />
In code behing when the usercontrol or window is loaded or when a button is pressed..put this:
testPanel.Children.Add(new Combobox()); --- something like this...
This way, you can assure that whatever you put in the stackpanel (it can be another grid or a dockpanel...) will appear before the button and that you can on runtime create the control you need.
regards,
SM

XAML: Is there a way to style TreeViewItem header property to contain multiple font styles?

I need to create a TreeView type controller that will display rich text.
Example:
» Signed by Person Name
» Certified by Person Name
Content of the TreeViewItem is easy as I can simply put TextBlock inside, but header don't allow for multiple font style declarations.
I'm really a beginner in XAML and I work in ExpressionBlend (although I don't shy away from coding). I would really appreciate if someone push me into right direction.
You can put a "Run" in a TextBlock to change the font.
e.g.
<TextBlock>Hello<Run FontStyle="Bold">World</Run></TextBlock>
You can set the content of the header to anything you want
<TreeViewItem>
<TreeViewItem.Header>
<TextBlock>Hello<Run FontStyle="Bold">World</Run></TextBlock>
</TreeViewItem.Header>
</TreeViewItem>
When you do this:
<TreeViewItem>Hello</TreeViewItem>
You are not telling the XAML parser what property you want to put 'Hello' into. The XAML parser will look at the type (TreeViewItem) and see which is set as the 'ContentProperty', in this case it's the property called 'Header'. Because you have not specified what 'Hello' is, it assumes a string. Since a string can't actually be displayed as content in WPF, it has to create a control to display the string. The ValueConverter for TreeViewItem is set up to provide a TextBlock control and set the Text of this control to the string you entered. So what's happening behind the scenes is a lot more than you can see :)
All of this stuff you can do with your own controls
You should probably read up on WPF templating, content controls, content presenter, styles etc. There are a lot of powerful things you can do with WPF - for instance, make every single button in your application have the same layout and style and add an image to the front of the button without any code (just with a few lines of XAML)
Have a look here for a beginners guide to templating
http://msdn.microsoft.com/en-us/magazine/cc163497.aspx

How to control placement ordering when using arrangeoverride to extend WPF controls

I am extending the WPF textbox in order to place a custom image on it. I want to capture mouse clicks on this image. So far i have been able to use arrangeOverride to place the image in where i need it but since it happens to be placed "inside" the text box, whenever i try clicking it the text box captures the click and the event that is attached to the image does not fire. Is it possible to indicate that the image should be placed on top of the text box when using arrange override? I know i can get around this issue if i extended a Control and placed a text box inside it, but for my application i need to actually extend a text box in order to be able to use it in another more complex control that is currently using a text box.
Thanks!
ArrangeOverride may not be the ideal solution for this. A better approach would probably be to use control templating: create a ControlTemplate containing a Grid with a single cell, and place the Image and the text box content host in that single cell. You can place the Image on top implicitly by the order you place the controls, or explicitly by setting the Panel.ZIndex attached property.
The one trick here is knowing how to represent the text box content host. This has to be a ScrollViewer with the name PART_ContentHost. So your template will look something like:
<ControlTemplate TargetType="{x:Type Ambog36sTextBox}">
<Grid>
<ScrollViewer x:Name="PART_ContentHost" /> <!-- WPF will fill in a text edit area here -->
<Image Panel.ZIndex="1" Source="..." />
</Grid>
</ControlTemplate>
Then assign this template to your custom text box class via the default style in the usual way.
As you are not using the standard composition model it means you need to override the mouse handling before it reaches the text box code and add your own custom logic to decide on the events to generate.

What is the difference between modifying a control by altering the control template and adding sub controls

I am new to WPF and I have a doubt in modifying a control. I came to know that one can modify a control by changing its Control Template. i.e.,
<Button>
<Button.Template>
<ControlTemplate>
...
</ControlTemplate>
</Button.Template>
</Button>
Also we can edit a control utilizing the Content Model. i.e.,
<Button>
<Grid>
<CheckBox>
</CheckBox>
<RadioButton>
</RadioButton>
...
</Grid>
</Button>
What is the difference between these two techniques. Which one is the correct way to customize a control in WPF. Please help me in understanding this better.
The primary difference between these two things, is that the ControlTemplate defines the look of the control. It is not actually placing content inside of it. At some location inside the content control, there should be some form of ContentPresenter. The built in controls are capable of this because they are what is known as 'lookless controls', and any custom controls created should also be lookless. When a control is not templated in a lookless manner but instead has a static layout, then the confusion you have run into can occur.
As for the correct way to do things, it depends on what you are trying to achieve. If you are attempting to change the control, such as the look and feel or the behavior, then using a ControlTemplate, (or DataTemplate, depending on what you are templating), is definitely the way to go. A good example of this is the CheckBox, belive it or not, the CheckBox is actually a ToggleButton (more or less), that through templating displays the togleablity in a bullet. Here's another very good example of how you can use Templates to do some very nifty things.
ControlTemplates should also be applied through Styles, instead of directly set on an element.
If you aren't actually aiming to modify the behavior or look of the control then using the content model is the correct approach.
WPF does this better then Silverlight, though I don't know if there are improvements in SL3.
My rule of thumb is that if it's possible to get what I want without changing the control template then you shouldn't change the control template.
control templates are a way to change the look&feel of a control, for example making a round button of changing the check mark graphics of a checkbox.
adding controls inside a control is simpler, for example place an image inside a button.
Also remember, there is a lot of functionality in the control template, including padding, content alignment, disabled look and more, if you change the control template you will have to add support for all of those features.
Template can be placed into a resource and re-used for another button.
Changing content directly is not re-usable unless you make a UserControl out of it.
Which one you use depends on a concrete task and your personal preferences.

Resources