I have this ControlTemplate that contains stuff (gradients in this case) that I want to be able to access programmatically and after hours of trial and error I feel that it's finally time to turn to you for assistance, StackOverflow.
The template generates a flower, and I didn't know what to use, so I just picked the Thumb-element, since I've used that before in a similar manner. If you can think of anything else that would be better suited, please let me know.
Anyways, this is the beginning of my ControlTemplate, from the XAML-file:
<ControlTemplate x:Key="cherryFlowerStyle" TargetType="{x:Type Thumb}">
<Viewbox Width="119.560" Height="114.268" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Canvas Width="119.560" Height="114.268">
<Canvas>
<!-- Layer 1/<Path> -->
<Path Data="... (removed to save space) ...">
<Path.Fill>
<RadialGradientBrush x:Name="cherryFlowerColorGradient" MappingMode="Absolute" GradientOrigin="593.380,333.416" Center="593.380,333.416" RadiusX="36.460" RadiusY="36.460">
<RadialGradientBrush.GradientStops>
<!-- Flower color -->
<GradientStop x:Name="cherryFlowerColorGradientOuterColor" Offset="0.15" Color="#ffd6e062"/>
And here's what I'm doing in C#:
Thumb flower = new Thumb();
flower.Template = TryFindResource("cherryFlowerStyle") as ControlTemplate;
GradientStop grStop = (GradientStop)flower.Template.FindName("cherryFlowerColorGradientOuterColor", flower);
Console.WriteLine("gradient: " +grStop);
Creating a new Thumb and applying the template works (it's drawn as a flower on the canvas).
Trying to access the gradients inside the template, however, does not work. I hope there's a good solution to this, or else I have to do it the ugly way; create a flower off-screen (in XAML) and reference that in the code-behind, because that works :/
Thanks in advance!
That won't work, because the Gradient is not a child of your template, its the value of the property of a child of your template. So you can access the Path by name, and modify its Fill value. But remember, the Gradient might be frozen.
Why not use binding and the DataContext for that? Or yet better, use dependency properties to modify the colors directly and just use TemplateBinding. It would be a much much better way to handle that, with less work. Also the Thumb element is used for moving elements and it encapsulates the mouse handling for that, if you don't need that the Control element would be a better base class. If you want performance, Visual or ContainerVisual would be much better, but also very limited.
Related
Is it possible to subclass a control (AppBarToggleButton in my case) and "inherit" TargetType of the base class? What I want to achieve is to have a slightly customized AppBarToggleButton (with disabled auto-toggle behavior) put into CommandBar and make it look exactly as if it was regular AppBarToggleButton (i.e. receive style whatever is defined for AppBarToggleButton inside given command bar control template). They say, DefaultStyleKey should help, but it is inherited fine, but, alas, doesn't seem to participate in local style resolution/lookup.
I may need to subclass other controls for various purposes, so the ultimate goal here is to understand how local style resolution works internally and does target instance has any involvement in it or is it a completely external process.
In general, we need make Templated Control for custom AppBarToggleButton. When we make Templated Control with Visual Studio, it will generate Generic.xaml file in the Themes folder that used to declare the custom control's style. And the the custom control cs file like the following.
public sealed class CustomAppBarToggleButton : AppBarToggleButton
{
public CustomAppBarToggleButton()
{
this.DefaultStyleKey = typeof(CustomAppBarToggleButton);
}
}
If you don't want to edit the default style you could remove DefaultStyleKey line that used to binding current control with the style in the Generic.xaml file.
Open Generic.xaml file you will find the following. And it's empty style. If we want to do some small changes, you need copy the complete AppBarToggleButton style to replace it and edit the TargetType to local:CustomAppBarToggleButton. Then you can edit the style base on your requirement.
<Style TargetType="local:CustomAppBarToggleButton" >
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:CustomAppBarToggleButton">
<Border
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And if your want to make a new dependency property, please define it in the cs file then use TemplateBinding to bind the property in the style. For more please check this document.
For anyone still stumbling upon this. I managed to solve a similar issue, inheriting from Button, using the approach described here https://stackoverflow.com/a/71338869/10468107
Specifically, adding
<Style BasedOn="{StaticResource DefaultButtonStyle}" TargetType="local:MyButton" />
solved it for me. So maybe it works for other types as well, using {StaticResource Default<TYPE>Style}
I have a similar need and am wondering if the answer is still the same. I have extended the basic ComboBox control to meet some behavioral requirements.
class ExtendedComboBox : ComboBox
I want the ExtendedComboBox instances to inherit the latest platform styling but they are instead getting styled differently. The first of these is an ExtendedComboBox (square corners, larger glyph), while the second is a generic ComboBox (rounded corners, smaller glyph).
The requirement is to have the two combo boxes styled the same way. I am reluctant to create an explicit Style for ExtendedComboBox because then if the style for the generic ComboBox changes the ExtendedComboBox will no longer match. Is there some way to just inherit the standard style?
I'm using WPF (and the MVVM framework) to create an interface which has a slider on it.
<Slider Value="{Binding MotorDemandSpeed}" Maximum="3500" />
I'm trying to hide the track part on the slider so that you are left with just the 'thumb tack'. This is what the slider currently looks like (styles are controlled by a theme):
I've looked around at various methods, however I can't find a method that changes only a single slider.
Help is appreciated.
You need to set the Template property of this particular Slider instance to be able to override its ControlTemplate:
<Slider Value="{Binding MotorDemandSpeed}" Maximum="3500">
<Slider.Template>
<ControlTemplate TargetType="Slider">
<!-- define the custom template without a track here... -->
</ControlTemplate>
</Slider.Template>
</Slider>
In order to change the appearance of a control you will need to modify the control template. Each control is made up of many parts, and each part many objects. You can modify individual parts (such as the track) with the correct x:Key and TargetType.
This Question has an example of modifying a scrollbar control template, which is most likely similar to the template of this slider you have. The first step would be to identify the Xaml file in your theme which this slider uses and find the parts that define the trackbar, thumb, etc. From there you should be able to recreate the control to your liking, or just completely remove parts you do not need.
Are you using any third party controls that may have information on how to edit their themes? Perhaps try investigating Modifying Control Templates to get a better understanding of control templates.
Here is the MDSN page for the slider control template, you may find this useful.
I am trying to build a GUI using WPF, in which I can draw some basic shapes and store them into a xml file. Shapes are designed in a xaml file, and I added tags for each of them. Now I want to get the value of their tags in my code to store as attributes in the output xml file.
For instance, I created a rectangle shape with a tag named "RectangleTag" in my xaml file like this:
<Style x:Key="stack" TargetType="Rectangle" BasedOn="{StaticResource FlowChartRectangleStyle}"/>
<Style x:Key="stack_DragThumb" TargetType="Rectangle" BasedOn="{StaticResource stack}">
<Setter Property="IsHitTestVisible" Value="true"/>
<Setter Property="Tag" Value="RectangleTag"/
</Style>
and
<Rectangle Style="{StaticResource stack}" ToolTip="stack" StrokeThickness="2">
<s:DesignerItem.DragThumbTemplate>
<ControlTemplate>
<Rectangle Style="{StaticResource stack_DragThumb}" x:Name="StackShape" Tag="RectangleTag" />
</ControlTemplate>
</s:DesignerItem.DragThumbTemplate>
</Rectangle>
Then in my code I did:
XElement myItem = new XElement("Items",
from item in designerItems
let contentXaml = XamlWriter.Save(((DesignerItem)item).Conent)
select new XElement("Item",
new XAttribute( "Tag", item.Tag.ToString())
);
Then my GUI stops responding for this line. I believe there must be some way to get the tag here but not in this manner obviously. How can I do that? It won't necessarily be the tag, but also the x:Name or x:Key, that are enough to let me differentiate the given shapes.
I also tried this line:
new XAttribute("Tag", item.Name)
But this gives out an empty string, not the name that is assigned in the xaml file. Could someone help? Thanks.
As Sheridan stated, you are attacking this problem from the wrong direction.
First of all - required reading if you haven't yet: Model-View-ViewModel Explained
You should create a set of Model objects that define your shapes, a set of ViewModel objects that expose them to the View and define their behavior, and a View which binds to the ViewModel.
A key difference in doing it this way is that now your logic for persisting to XML is not dependent on the UI at all, so you won't have to try to use something like Tag to pass around 'magic values'.
And, as an aside, I have found that the vast majority I've relied on using Tag for anything, that has been an indicator that I'm Doing It Wrong. :)
Here is a example: assuming you have UI element is XAML (Button named _btn) with Tag property set to some value, then in any event handle (e.g. Click) associated with that element in code behind you can get the Tag value as follows:
_btn.Click+=(s,e,)=>{ string _tag = (s as Button).Tag.ToString(); };
You can apply the same logic to you case. Rgds,
I want to make a WindowBaseClass that derives from Window but has a few custom functionalities. Such that WindowStyle would be none, I have my own color scheme applied and also have a resize logic.
Here is a snippet of the XAML that contains one of the 'borders' that has a MouseMOve and PreviewMouseDown events.
<Rectangle Stroke="{x:Null}" x:Name="top" VerticalAlignment="Top" Height="5"
Grid.Column="1" Grid.Row="0" PreviewMouseDown="Resize"
MouseMove="DisplayResizeCursor">
<Rectangle.Fill>
<SolidColorBrush Color="{StaticResource Ocean}"/>
</Rectangle.Fill>
In my code behind I have methods such as resize, drag etc. When it is all contained in a Window1.xaml/.cs it's all working nice.
Now I want to create a custom template (in a resource dictionary for example) with my color schemes and I want the PreviewMouseDown from the rectangle to point to the method defined in a class that extends Window.
Can it be done? Any help would be greatly appreciated.
I don't think you'd approach it quite like that. I think you'd subclass Window and add in your custom PreviewMouseDown logic, etc. and then you would set up the styles for your new subclass in the resource dictionary.
You might also want to look into a custom attached property.
If PreviewMouseDown, etc. are doing logic specific to one window as opposed to general functionality, this probably isn't going to work out so great either way.
What are the best practices for designing a simple component, for example a border with a background, rounded corners and a textblock with specific styling inside? What I need to be able to do is add this component on many different objects (basically a styled label for the items). The easiest way to design such a thing, in my opinion, is via XAML, but how do I create more of these objects from the code behind?
Another option would of course to just write it all in code, but it is much slower to design the look by just looking at code. I tried googling around a bit but I suppose I am simply not figuring out the correct keywords because I was unable to find anything of use.
I think there are multiple ways of doing this. Depends on what exactly you want to achieve. You would want to read up on the following in WPF
1. UserControls
2. CustomControls
3. Styles
4. Templates
5. Resources
You could use a ContentControl and set its template. Your template would be the border/background/rounded corners etc...
<DataTemplate x:Key="MyTemplate">
<Border>
...
<TextBlock Text="{TemplateBinding Content}" />
...
</Border>
</DataTemplate >
You'd use it like this:
<ContentControl ContentTemplate="{StaticResource MyTemplate}" Content="blah blah" />