how can i use a control in template? - c#

<Style x:Key="abc" TargetType="{x:Type Window}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Window}">
<button x:name="btn">my button!!</button>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
...
<Window ... Style="{StaticResource styleMainWindow}">
How can i use the button btn?
come up to your expectations,
MessageBox.Show(this.btn1.name);
was occured an error at compile time. and also btn1 didn't show up in intelisense.

Try the FindName method on the ControlTemplate class.
Assuming this is your Control's context:
var button = (Button)this.Template.FindName("btn", this);

I guess mjk6026, you have misunderstood WPF templates from actual member elements of a window.
It is true that when we name a UI element (x:Name) that is not part of any template, we can access that element by name in the code behind.
For templates you would have to use Template type's FindName() method.
So assuming that `this' means the window to which you have applied your style, the way you can access the button is (Button)this.Template.FindName("btn", this)
Let me know if this answers your question...

Related

WPF Override Style Value

I'm using MaterialDesignInXaml for WPF which provides 3rd party controls and styles. I need to edit one of these styles by changing one property.
I am using an Expander control which has a template creating a bunch of child controls. I've discovered the child 'Border' control (4 layers deep) has the property (padding) which I need to set to zero.
See this output from Snoop showing the property I need to change:
Link to image
My question is how can I do this? I've tried extending the style used by the control as follows, but it isn't changing anything so I assume I'm doing something wrong?
<Style TargetType="{x:Type Expander}"
x:Key="MaterialDesignExpanderHeadless"
BasedOn="{StaticResource MaterialDesignExpander}">
<Style.Resources>
<Style TargetType="{x:Type Border}">
<Setter Property="Padding" Value="0"></Setter>
</Style>
</Style.Resources>
</Style>
I am able to use the style like this. And I know this is working for sure:
<Expander Header="Header Content" Style="{StaticResource MaterialDesignExpanderHeadless}">
Some Content
</Expander>
You're right, this method should work. Something else is setting the border's padding.
Snoop is telling you the padding is defined by the parent template, which could be the HeaderSite (ToggleButton).
You could try to extend the ToggleButton style (BasedOn) or redefine it locally.

WPF window style applied to wrong windows

I have created custom window classes for dialogs like this:
public class DialogBase : Window
{
// common stuff here
}
public class DialogOkCancel : DialogBase
{
static DialogOkCancel()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(DialogOkCancel),
new FrameworkPropertyMetadata(typeof(DialogOkCancel)));
}
// specific stuff here
}
The styles looks like this, and contains dialog specific things such as title bar, OK/Cancel buttons etc.
<Style x:Key="DialogBaseStyle" TargetType="{x:Type base:DialogBase}" BasedOn="{StaticResource {x:Type Window}}">
<Setter Property="ShowInTaskbar" Value="False"/>
<!-- more stuff here -->
</Style>
<Style TargetType="{x:Type base:DialogOkCancel}" BasedOn="{StaticResource DialogBaseStyle}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type base:DialogOkCancel}">
<!-- more stuff here -->
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
This works perfectly fine during runtime. Also, the dialogs displays fine in XAML Designer.
However, in XAML Designer, the DialogOkCancel style gets applied to other all other windows as well, such as the application main window (which simply derives from plain Window). The title bar, buttons and everything. I don't really get this, as the TargetType is specific. This does not occur at runtime.
What am I not seeing here ?
Correct way to apply a style both while in designer mode and during runtime is to have declared the style in App.xaml. Best practice would be to have a MergedDictionaries, containing a reference of your various style dictionaries, which will be in other files.
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!-- Converters -->
<ResourceDictionary Source="Resources/Converters.xaml"/>
<!-- Windows -->
<ResourceDictionary Source="Resources/WindowStyles.xaml"/>
// ... and all others //
WindowStyles.xaml can contain the exact styles you wrote above. They will be applied to all DialogOkCancel windows, both in designer and runtime.
Hope that helped.

Modify Style (add a trigger) dynamically on runtime

I want to add some graphic items on runtime in my object of my WPF application. My goal is to add a circle around my button (only by codebehind on runtime) and to add a trigger to my ControlTemplate.
Everything is fine, my circle around my button shows up BUT my problem is: I cannot create any trigger, it says:
After a 'TriggerCollection' is in use (sealed), it cannot be modified.
What I understand is I cannot modify a Style when it's rendered or used by something else.
I tried to copy the Style to modify the new one but I can't access to the trigger.
My object is like this:
<Style x:Key="Button_1" TargetType="{x:Type MyDLL:MyObject}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type MyDLL:MyObject}">
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Width="190" Height="140">
....
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="Property1" Value="True">
<Setter.../>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
If I copy my Style to a new style, how can I add the trigger into the ControlTemplate?
If I copy my ControlTemplate to a new ControlTemplate, the new one is also sealed.
My code behind to create my trigger is:
Trigger trigger = new Trigger { Property = DragModeProperty, Value = false };
Setter setter = new Setter { Property = VisibilityProperty, Value = Visibility.Collapsed, TargetName = "DRAG" };
trigger.Setters.Add(setter);
Template.Triggers.Add(trigger); // THIS ONE CAUSE THE ERROR
Found it.
I just create my trigger on a new container (Grid) instead of on my Button.
Simple.

Disable Style in WPF XAML?

Is there anyway to turn off a style programatically?
As an example, I have a style that is linked to all textboxes
<Style TargetType="{x:Type TextBox}">
I would like to add some code to actually stop the style elements being used, so basically reverting back to the default control style.
I need a way to make a switch in my styles, so I can switch between Windows default style and my custom style through C# code.
Is there anyway to do this?
Thanks
Working Solution
Switching between themes in WPF
For setting the style to default,
In XAMl use,
<TextBox Style="{x:Null}" />
In C# use,
myTextBox.Style = null;
If style needs to be set as null for multiple resources, see CodeNaked's response.
I feel, all the additional info should be in your question and not in the comments. Anyways, In code Behind I think this is what you are trying to achieve:
Style myStyle = (Style)Application.Current.Resources["myStyleName"];
public void SetDefaultStyle()
{
if(Application.Current.Resources.Contains(typeof(TextBox)))
Application.Current.Resources.Remove(typeof(TextBox));
Application.Current.Resources.Add(typeof(TextBox),
new Style() { TargetType = typeof(TextBox) });
}
public void SetCustomStyle()
{
if (Application.Current.Resources.Contains(typeof(TextBox)))
Application.Current.Resources.Remove(typeof(TextBox));
Application.Current.Resources.Add(typeof(TextBox),
myStyle);
}
You could inject a blank Style that would take precedence over your other Style. Like so:
<Window>
<Window.Resources>
<Style TargetType="TextBox">
<Setter Property="Background" Value="Red" />
</Style>
</Window.Resources>
<Grid>
<Grid.Resources>
<Style TargetType="TextBox" />
</Grid.Resources>
</Grid>
</Window>
In the example above, only the Grid's implicit Style would be applied to TextBoxes in the Grid. You could even add this to the Grid programmatically, something like:
this.grid.Resources.Add(typeof(TextBox), new Style() { TargetType = typeof(TextBox) });
I know the answer has been accepted, but i want to add my solution which works awesome in the following scenario:
One main application using mahapps.metro
additional project imported from the main application with no reference to mahapps.metro, it is imported as a plugin (loading compiled .dll on the fly)
using the < ToolBar> re-styles everything to null therefore the mahapps.metro styles are not being applied to items inside the toolbar.
usercontrol is used to provide custom controls to the main application.
in the user control root set the resources:
<UserControl.Resources>
<Style x:Key="ButtonStyle" TargetType="Button" BasedOn="{StaticResource {x:Type Button}}" />
<Style x:Key="ComboBoxStyle" TargetType="ComboBox" BasedOn="{StaticResource {x:Type ComboBox}}" />
</UserControl.Resources>
then the toolbar code can be the following
<ToolBar>
Block Template:
<ComboBox Style="{StaticResource ComboBoxStyle}"/>
<Button Content="Generate!" Style="{StaticResource ButtonStyle}"/>
</ToolBar>
this successfully applies the main application style to the controls inside the < ToolBar>
In Xaml, you can override this by setting a style explicitly. In code-behind, you can also set the style explicitly.
<TextBox Style="{StaticResource SomeOtherStyle}"/>
myTextBox.Style = Application.Resources["SomeOtherStyle"];

What is the recommended way to skin an entire application in WPF?

I want my WPF application to be skinnable, by applying a certain XAML template, and the changes to be application wide, even for dynamic controls or controls that aren't even in the visual/logical tree.
What can I use to accomplish this type of functionality? Are there any good resources or tutorials that show how this specific task can be done?
The basic approach to take is using resources all through your application and dynamically replacing the resources at runtime.
See http://www.nablasoft.com/alkampfer/index.php/2008/05/22/simple-skinnable-and-theme-management-in-wpf-user-interface/ for the basic approach
The replacing of resource will work but I found "structural skinning" to be more powerfull! Read more about it on CodeProject...
http://www.codeproject.com/KB/WPF/podder1.aspx
I have found the way to apply generic templates to all controls without using template keys. The solution is to use the type of the control as the Style key.
Example:
<Application.Resources>
<Style x:Key="{x:Type Button}" TargetType="{x:Type Button}">
<Setter Property="Button.Background" Value="CornflowerBlue"/>
<Setter Property="Button.Template">
<Setter.Value>
<ControlTemplate x:Name="MyTemplate">
...
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Application.Resources>
here the Style key is x:Key="{x:Type Button}", so the style will be applied to all controls of type button without the control declaring the Style property to be a static or dynamic resource.

Categories

Resources