WPF Howto create a reusable composite component with configurable content? - wpf

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

Related

How to style a custom Silverlight 4 UserControl?

I have a custom UserControl that I created as a navigation menu that parses an xml file and populates itself with hyperlink buttons. So basically my control is an empty stackpanel, and when it's loaded it adds hyperlinkbuttons as children to the stack panel.
In my application I just add a <myLibrary:NavigationMenu links="somexml.xml" />
The problem is that I want to be able to style the hyperlinkbuttons and the stack panel differently for every application. What is the best way to do this.
In the code behind for the control, create a DependencyProperty of type Style for both HyperlinkStyle and StackPanelStyle. Then when you create the items apply the correct styles too them.
Take a look at MSDN
The article is a good starting point for writing stylable controls.

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.

Retemplating a Button control with custom properties possible?

I made myself a TransparentButton style that makes the Button portion behave the way I want it to (mouseover, enabled, etc), but what I haven't been able to do is set the content correctly in the style. Currently, I manually set everything in <Button.Content> for every button, and clearly that stuff needs to go into the Style. I have set the ContentTemplate for the style to a StackPanel that just contains an Image and a Label. The problem is, I don't know how to specify in my <Button ...> markup the Label's text and the Image's Source. I figured that it had to do with TemplateBinding somehow, but I've been searching like crazy and can't seem to find the information.
So, in summary, I just want a consistent button style where the button content is just a StackPanel of an Image and a Label, and I want to be able to create it in my GUI with something simple like:
<Button Style={DynamicResource TransparentButton}"
Label="Click Me" Image="Images/MyImage.png" />
Any tips would be much appreciated! I hope I'm on the right track here...
In order to create custom properties like this, you'll need to make a CustomControl instead of just using a Button style.
This is fairly easy, though - just make a custom control that subclasses button, and adds your new properties (as dependency properties). This will make it stylable, but also provide you the ability to enforce that those properties are always available, with the syntax you're describing (other than changing <Button to <local:MyButton).
For details, see the Control Authoring Overview on MSDN.

When writing the xaml for my user controls should I remove grid and use dock panel or something else?

I am adding user controls in my solution. The main page of my project will have a dock panel. When writing the xaml for my user controls should I remove grid and use dock panel or what? Iam using visual studio express and WPF.
The answer is it depends on what you want your control to look like.
Remember the Grid is to help you orgainze your controls. You can define features like columns widths, row heights, and other styling.
While a dock panel is to help dock your control to a part of the form or another.
So it depends on what you want your control to look like. You can nest a grid in a dock panel and vice versa. There is no set rule. It is really up to you.
Inside your user controls, use whatever type of panel makes sense for the contents of that control. In the main page, you set the DockPanel.Dock attribute on your user control, but that is independent of what's inside the user control.
It really depends on what you want to do.
Your top level may not even be a panel. For example, if you only want one control in the user control, then you really don’t need the panel.
Also, in some cases, even with composite controls, you may want to put something other than a panel as the top level control, for example, an expander.
Further, if you want to create a control that is very similar to another control, but behaves a little different, you may not even want to use a user control and instead inherit from an existing control. An example of this would be a numeric textbox that inherits from a textbox but adds keypress filtering.

How can I make a Button with multiple content values?

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>

Resources