Binding to value of property from inside style template failing - c#

I'm having an issue with attempting to bind the Fill property of an Elipse (in a ToggleButton control) to a custom DependencyProperty of another control.
Below is the XAML code raising the "Property path is not valid" error - It's a Resource dictionary file for the Expander control.
The erroneous line:
Value="{Binding Path=(local:Expander.ToggleButtonMouseoverColor)}"
The first code block - the MixSelectorExpanderButtonStyle is attached to a style definition for an expander, seen in the second code block.
<Style x:Key="MixSelectorExpanderButtonStyle" TargetType="{x:Type ToggleButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter TargetName="Circle" Property="Fill" Value="{Binding Path=(local:Expander.ToggleButtonMouseoverColor)}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I'm confident the property is correct - in the same file, I am able to access the ToggleButtonMouseoverColor property without error:
<Style TargetType="{x:Type local:Expander}">
<Style.Triggers>
<Trigger Property="Status" Value="0">
<Setter Property="ToggleButtonMouseoverColor" Value="{DynamicResource ZKGeneric_Highlight_MouseOver}" />
</Trigger>
</Style.Triggers>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Expander}">
<ToggleButton style=""{StaticResource MixSelectorExpanderButtonStyle}" />
</ControlTemplate>
</Setter.Value>
</Setter.Value>
</Style>
When I remove the local: prefix from the path, the error changes to the property not being recognized or accessible.
If I name the style definition and change the binding to:
Value="{Binding Path=ExpanderStyle.ToggleButtonMouseoverColor}"
I am able to build and run it, however it appears to just be a null value.
Clearly I'm missing some syntax to properly point to the property, but this is the first time i have attempted to bind in such a convoluted manner.
If not, is there a more optimal way to define this behaviour?
Any help would be appreciated, in the meantime, I shall attempt to consult my WPF programmer's reference.
EDIT:
I forgot to mention, I have also been trying to use Value="{Binding ToggleButtonMouseoverColor, RelativeSource={RelativeSource TemplatedParent}}", among other variations, but can't seem to get it working.

I believe you want this, although it sounds like you've potentially tried it? I have no idea why it wouldn't work...
Value="{Binding ToggleButtonMouseoverColor, RelativeSource={RelativeSource AncestorType={x:Type local:Expander}}}"

Related

"Enter" key not leaving cell in RadGridView

All around my project I'm facing similar problem, which is "Enter" key, creating new line in cell, instead of move to next line.
My current telerik version is 2018.1.122.45, and default, expected behavior is to leave cell, after pressing "Enter" key (according to telerik documentation, and helpdesk).
However, in my case it always makes new line within cell being edited.
I'm using Visual Studio 2013 theme, my implementation of RadGridView is correct, I've pasted my RadGridView, to project, I got from telerik support, and there, Enter was working as expected. Also, they've pasted my RadGridView implementation to their project and it also worked correctly.
Have anyone faced similar problem? I'm looking for solution, since I can't track source of this issue (even with teleriks help).
I've found a solution to this problem, and other Styles problems. Implementing style in the way demonstrated in telerik documentation (f.e. https://docs.telerik.com/devtools/wpf/controls/radgridview/styles-and-templates/styling-a-row) has some issues not mentioned in documentation.
<Style TargetType="telerik:GridViewRow">
<Setter Property="Background" Value="Red"/>
<Setter Property="Foreground" Value="White"/>
</Style>
This is one of the simpliest examples of implementing style. In my case it was:
<Style TargetType="telerik:GridViewCell"
x:Key="IloscNormalStyle"
BasedOn="{StaticResource GridViewCellStyle}">
<Setter Property="Background"
Value="#c3d8c7" />
<Setter Property="Foreground"
Value="Black" />
</Style>
And it works just fine. The biggest issue is that it completly ignores implemented Theme for project and all it's behaviours, which are, for example, selection behavior, enter key press, borders, etc. In order to tell style to not ignore implemented theme, I needed to insert this code to my styles:
<Style.Triggers>
<DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=telerik:GridViewRow}}"
Value="True">
<Setter Property="Background"
Value="{Binding Background}" />
</DataTrigger>
</Style.Triggers>
Which finally made my style works with desired behavior. Full style code:
<Style TargetType="telerik:GridViewCell"
x:Key="IloscNormalStyle"
BasedOn="{StaticResource GridViewCellStyle}">
<Setter Property="Background"
Value="#c3d8c7" />
<Setter Property="Foreground"
Value="Black" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=telerik:GridViewRow}}"
Value="True">
<Setter Property="Background"
Value="{Binding Background}" />
</DataTrigger>
</Style.Triggers>
</Style>
I think it is a major issue for telerik (or maybe even WPF), but this couple lines of code resolves most of problems with custom cell/row styling.

WPF changing margin pushes other elements down

First of all, sorry for my bad English.
I'm trying to make buttons "pop?" in my application when I hover the mouse over them.
This is what I came up with:
<Style x:Key="SelectButton" TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="False">
<Setter Property="Content">
<Setter.Value>
<Image Source="\directory"/>
</Setter.Value>
</Setter>
<Setter Property="Margin">
<Setter.Value>
<Thickness Bottom="10" Right="10" Top="10" Left="10"/>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Content">
<Setter.Value>
<Image Source ="\directory"/>
</Setter.Value>
</Setter>
<Setter Property="Margin">
<Setter.Value>
<Thickness Bottom="0" Right="0" Top="0" Left="0"/>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
You can see how it looks compiled here:
The problem is, whenever I change the margin of the button, it pushes every single other element of the application down. I'm honestly out of ideas.
Thanks, in advance.
Well, you're resizing the button, which would cause this behavior. It's completely expected.
Fortunately for you, what you REALLY want to do is apply a RenderTransform. They don't affect layout. From the docs,
A render transform does not regenerate layout size or render size information. Render transforms are typically intended for animating or applying a temporary effect to an element. For example, the element might zoom when focused or moused over, or might jitter on load to draw the eye to that part of the user interface (UI).
You'll want to use a ScaleTransform. Transforms are fun. It won't be long after you use one that you realize you can animate them, and then you'll be animating them.

Set property in ContentPresenter child control

I want to set TextTrimming on TextBlock.
<Style TargetType="{x:Type dg.CellValuePresenter}">
<Setter Property="ContentTemplate" Value="{StaticResource Tmp}" />
</Style>
My template:
<DataTemplate x:Key="Tmp">
<ContentPresenter Content="{Binding}" >
<ContentPresenter.Resource>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="TextTrimming" Value="CharacterEllipsis"/>
</Style>
</ContentPresenter.Resource>
</ContentPresenter>
</DataTemplate>
Content Presenter is XamTextEditor from Infragistic:
<Style TargetType="{x:Type igEditors:XamTextEditor}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type igEditors:XamTextEditor}">
<TextBlock/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Setter from DataTemplate doesn't work. Do you know how to set this property?
How can I set TextTrimming property in Textblock of XamTextEditor cudtom style? I cannot do this in this style because it is used in other datatemplates where texttrimming must be turn off. So I tried to set it in DataTemplate but it not work (i see in snoop that it is set to none)
Unfortunately I cannot show more code because I don't have access to internet on dev and write down more code is time consuming :/
I'm not sure if I get your problem completely.
But If you are using explicit column definition. Then instead of CellvaluePresenter try create a EditorStyle For any column type(I've done it for string type column so the editor would be XamTextEditor)
<!--(xmlns:igWindows="http://infragistics.com/Windows")-->
<Style TargetType="{x:Type igEditors:XamTextEditor}" x:Key="DefaultXamDateTimeEditor">
<Style.Resources >
<Style TargetType="{x:Type igWindows:SimpleTextBlock}" >
<Setter Property="TextTrimming" Value="CharacterEllipsis" />
</Style>
</Style.Resources>
</Style>
And use this style as columns EditorStyle. It should work in XamDatagrid as this is working for me. Please post specific situation If I didn't get the question right.

TreeViewItem to notify ViewModel when it is hovered

I am currently using the code from this blogpost in order to have my TreeView highlight those items, which are currently hovered by the mouse. This is working as intended, however now I want the TreeViewItems to notify their attached ViewModels when they are hovered / not hovered.
However I'm at a loss on how I can achieve this. The corresponding XAML code looks like the following:
<Style TargetType="{x:Type TreeViewItem}">
<Style.Triggers>
<Trigger Property="Controls:TreeViewHelper.IsMouseDirectlyOverItem" Value="True">
<Setter Property="Background" Value="Green" />
</Trigger>
</Stile.Triggers>
</Style>
How can I bind the property from my ViewModel, named TreeNodeModel.IsHovered to the TreeViewItem (or probably the attached dependency property IsMouseDirectlyOverItem) so that I can react on those changes from within my code?
All the examples I found via google only explained how the set the background color. Thanks in advance for your time on the probably trivial answer.
In your Style, try adding a Setter which binds IsMouseDirectlyOverItem to IsHovered, and use the OneWayToSource binding mode to push the value the right way:
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="Controls:TreeViewHelper.IsMouseDirectlyOverItem"
Value="{Binding Path=IsHovered, Mode=OneWayToSource}" />
<Style.Triggers>
...
</Style>
EDIT: As IsMouseDirectlyOver is read-only, and read-only DPs can't be the target of any bindings, Fredrik Hedblad's PushBinding may be a possible workaround: OneWayToSource Binding for ReadOnly Dependency Property
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="pb:PushBindingManager.StylePushBindings">
<Setter.Value>
<pb:PushBindingCollection>
<pb:PushBinding TargetDependencyProperty="Controls:TreeViewHelper.IsMouseDirectlyOverItem"
Path="IsHovered" />
</pb:PushBindingCollection>
</Setter.Value>
</Setter>
<Style.Triggers>
...
</Style>

Variables in XAML Style

I have the following Style:
<Style x:Key="ButtonBase" TargetType="Button">
<Setter Property="Background" Value="#FF007BFF"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<ControlTemplate.Triggers>
<Trigger Property="IsPressed" Value=">
<Setter Property="Background" Value="Yellow" />
<Setter Property="Foreground" Value="Black" />
</Trigger>
<Trigger Property="IsPressed" Value="False">
<Setter Property="Background" Value="#FF007BFF" />
<Setter Property="Foreground" Value="White" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<Setter.Value>
</Setter>
</Style>
and an inherited Style:
<Style x:Key="ElementButton" TargetType="Button" BasedOn="{StaticResource ButtonBase}">
<Setter Property="Margin" Value="10"/>
<Setter Property="Height" Value="200"/>
</Style>
What I'd like to do is be able to set an arbitrary variable in the base style:
<Setter Variable="HoverColor" Value="Pink"/>
Then I'd be able to use my triggers as such:
<Trigger Property="IsPressed" Value=">
<Setter Property="Background" Value="{TemplateBinding HoverColor}" />
<Setter Property="Foreground" Value="Black" />
</Trigger>
And finally, I could then override it in my inherited style:
<Style x:Key="ElementButton" TargetType="Button" BasedOn="{StaticResource ButtonBase}">
<Setter Property="Margin" Value="10"/>
<Setter Property="Height" Value="200"/>
<Setter Variable="HoverColor" Value="Red"/>
</Style>
Is there a way to achieve this? I've already looked at static resources but these can't be overridden. Also, I cannot use anything that requires a code-behind because I don't have one!
Its a good question and I've fought through this sort of thing as well. There may be some kind of XAML-only approach that could work, but I have a feeling that if there is, it would feel pretty kludgy. I have a couple of suggestions of how achieve what you want.
First, a quick observation. You say you "don't have a code-behind" and that your view is "XAML-only". Well, I've never seen a UserControl View that doesn't have any code-behind file at least, so I'm assuming you mean you just don't want to put any code in there (other than the obligatory InitializeComponent()). Having said that, the approaches that I'll outline won't require code in your code-behind files.
At the end of the day, it sounds like what you really want is define some custom "variables". These suggestions do just that, albeit maybe not in the way that you originally envisioned doing so.
The first approach that would solve your problem is to subclass the control that you are interested in styling and add any custom dependency properties to it. For example, you could subclass Button, to say something like ButtonWithMyVariables. One of those custom dependency properties would be called "HoverColor", of type Color, or perhaps more appropriately, "HoverBrush" of type Brush (if you're wanting to just apply it directly to the background or foreground property). Then your base Style can set HoverColor to whatever it wants, and your inherited Style can override it, or you can override it directly on the element in your XAML. I'm not providing code samples for this approach (right now, unless requested) since this is a more commonly-used approach that I'm guessing you're already familiar with.
The second approach would be to define a custom attached property. I've not seen this approach used as much for dealing strictly with Styling issues, perhaps because for the attached "behavior" to fully do its job in this case, authors have used Style files to react (bind to) and apply visual changes based on the attached property, rather than the code in the attached property changed callback doing something stylistically (but I suppose it could still be done that way). However, this approach feels "lighter weight" to many, since you don't need to subclass any existing controls.
An example of this second approach can be found in the MahApps.Metro library, specifically the TextboxHelper class (which houses attached properties) and the Controls.TextBox.xaml style file (which binds to those attached properties). For example, we see in the control template for the TextBox, this line that makes use of the Watermark attached property:
<TextBlock x:Name="Message"
Text="{TemplateBinding Controls:TextboxHelper.Watermark}" Visibility="Collapsed"
Foreground="{TemplateBinding Foreground}" IsHitTestVisible="False" Opacity="0.6" HorizontalAlignment="Left" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Margin="6,0,0,0"/>
Now you can imagine that you could set that Watermark value in a base style to something:
<Setter Property="Controls:TextboxHelper.Watermark"
Value="My helpful watermark for all!"/>
And then override it in an inherited style:
<Setter Property="Controls:TextboxHelper.Watermark"
Value="A more specific watermark!"/>
With either approach, we can define any "variable" we want and easily set them in a Style setter, override them in inherited styles, TemplateBind to them within control templates, or Trigger off of them.

Categories