XAML: Get parent background - wpf

I need to set a control's background to the color of the parent's background in XAML. Why not simply make the background transparent? It's a button with a drop shadow, so I need to set the background; otherwise, the drop shadow shows through.
So, from my control's markup, how do I set the Background property equal to whatever the parent (host) Background is? Thanks for your help.

You should be able to set the binding using:
<Button Background="{Binding Path=Background, RelativeSource={RelativeSource Mode="FindAncestor" AncestorType="{x:Type Control}" AncestorLevel="1"}}" />
Since Background is defined for any "Control", this should grab the control one ancestor up the tree, and use it's background.
Another option to consider would be to just make a button style that shows the background as transparent, but actually still draws the drop shadow/border. This would allow it to work on any UIElement.

I am going to leave Reed's answer as accepted, since it does answer my original question. But I discovered that I actually need to bind to the window in which the button is hosted. Here is markup to do that:
<Button Background="{Binding Path=Background, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}">My Button</Button>

Related

Issue with WPF styles

I wonder if someone can help, I am designing a custom WPF window for an application i am working on and I have an issue with the Min, Max and Close buttons. I have designed a ControlTemplate for the 3 buttons and they are in a StackPanel with Vertical orientation. In my base style I have the following
<Style x:Key="BaseWindowButtonStyle" TargetType="{x:Type Button}">
<Setter Property="Foreground" Value={Binding RelativeSource={RelativeSource AncestorType={x:Type FrameworkElement}}, Path=(TextElement.Foreground)}" />
<Setter Property="Background" Value="Transparent" />
...
</Style>
Have also tried setting the Foreground to a specific color such as #FF000000 and nothing displays
I have a style that inherits this style for the buttons but does not change the foreground or background.
My problem is that the button content does not display, the button displays and the IsMouseOver trigger fires which changes the background but the textual content never displays.
The Min button style is
<Button x:Name="PART_Min">
<Path Fill="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}"
Data="F1M0,6L0,9 9,9 9,6 0,6z"
SnapsToDevicePixels=True" />
</Button>
I am at a loss as to why the content does not display so would appreciate your thoughts.
The Visual Tree is below, I have examined this and identified the Foreground values
Window (Foreground: #FF000000)
Grid
AdornerDecorator
Grid
ContentControl (Foreground: #FF000000)
StackPanel
Button (Foreground: #FF000000)
Grid
ContentControl (Foreground: #FF000000)
But like I said above I have removed the binding and specified a physical value and still do not get the content displaying
Use ContentPresenter instead of ContentControl in your button's template. (You should include the button's control template in a question like this... it's potentially highly relevant.)
As I too was a beginner with WPF, and trying to understand things was a bit of a learning curve, I would like to offer a few previous links posted out here.
First a simple style for creating simple label and having all labels as a default take on this format without explicit style assignments.
Another sample showing creation of a custom button. This is where I went step by step to create a custom class and apply a style to it to show/hide image on a button.
Maybe the button link and style declaration will help you find your button coloring issues too.

WP7 -- Context Menu Forces Black Background for Listbox

This is probably an easy one... I have a Listbox with a ContextMenu embedded in it, and every time the ContextMenu appears, the Listbox changes its background to opaque black. How do I prevent this from happening?
Here is some sample XAML:
<ListBox x:Name="FolderItems" ItemTemplate="{StaticResource ItemTemplate}" ItemContainerStyle="{StaticResource ItemListBox}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}" ItemsSource="{Binding FolderItems}">
<toolkit:ContextMenuService.ContextMenu>
<toolkit:ContextMenu
x:Name="FolderContextMenu"
Margin="20"
Background="WhiteSmoke"
BorderBrush="Black"
BorderThickness="1.0"
Closed="ContextMenu_Closed">
<toolkit:MenuItem Loaded="ContextMenuItem_Loaded"
Opacity="0.0" Margin="5" Background="Transparent"
Click="ContextMenuItem_Click" Name="ContextMenuDelete">
<toolkit:MenuItem.Header>
<TextBlock Text="delete" FontFamily="Segoe WP Bold"/>
</toolkit:MenuItem.Header>
</toolkit:MenuItem>
</toolkit:ContextMenu>
</toolkit:ContextMenuService.ContextMenu>
</ListBox>
Thanks
Update
I still haven't figured out why the entire listbox goes black when the context menu appears. I've set everything I can think of to a transparent brush.
I fixed this for my situation by opening up the toolkit (downloading the source: Silverlight Toolkit), and editing the color values myself in ContextMenu.cs . Then, I rebuilt and targeted the dll that I created rather than the one from the installer.
The only issue is that I will now need to do this application specific, but at least I can have a resolution. I believe also that if you set IsZoomEnabled=false, it won't have this behavior in the first place, but it's a different experience.
Here's my edited version: Pastebin
Check out the lines like this, they're the ones you'll need to change:
// Create a layer for the element's background
UIElement elementBackground = new Rectangle
{
Width = ownerElement.ActualWidth,
Height = ownerElement.ActualHeight,
Fill = new SolidColorBrush(Colors.White),
};
Good luck!
There's a simple way to do this. For some reason MS Access complements the colors when using a list box. If you set the foreground to red, it will show green, etc.
So, set the background color to black (0) and the foreground color to white (16777215). Counter-intuitive but it works is MS Access 2002.
Without seeing the template you're using I can't say for sure but you've probably hardcoded a background value but not considered the different states of the list items and the default state colour/value is being displayed

Hyperlinks are staying inactive after setting isEnabled=true to parent control

I've got a TabItem contanining a listbox, which has an obeservable collection of my feeds class as its item source. When I refresh/load the feeds into the collection I want to disable the main window so that the user can't go clicking other things while this process is running. So I set tbCtrl.isEnabled=false; to my tab control on the form. Then assign an event handler to the a custom finish event which is triggered after all the feeds are loaded.
This all works fine, however the hyperlinks for the results which are currently displayed on the tab control never get re-enabled (Nor do the next few which are out of view due to the list box size). All the other results further down are fine, as are the results on the other tab.
I've tried calling InvalidateVisual on the tab control after everything is finished, to see if that makes a difference but that doesn't seem to cause any change.
I could understand it if it was all Hyperlinks doing it, or just the ones currently displayed, but I don't understand why ones which are out of scroll are not working either.
I hit the same issue.
What I did is to bind HyperLink's IsEnabled to the parent, and put that in an App global resource.
<Style TargetType="{x:Type Hyperlink}">
<Setter Property="IsEnabled" Value="{Binding IsEnabled, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type FrameworkElement}}}" />
</Style>
I found the answer for my case of the hyperlink not getting re-enabled, not sure if it applies to yours:
I found that when the Hyperlink's parent control is disabled (IsEnabled=false), the Hyperlink will not get notified of changes, e.g. IsEnabledChanged does not get fired, even when the bound property changes value.
My solution was to change my Xaml to no longer disable the ancestor control (which was causing the Hyperlink's parent to be disabled). With the parent (TextBlock) always enabled, now Hyperlink updates properly always.
(I'm a little bothered that the IsEnabled binding behaves differently than Controls do, and I'm not sure what I would do if I couldn't leave the ancestor enabled... but at least this lets me understand the issue I was having, and lets me work around it.)
Details: WPF 3.5 SP1
It's not just HyperLinks. It seems to be more specifically TextBlock which of course is what you use to wrap a HyperLink in WPF. This will give the same issue :
<TextBlock>
<Run Text="Barcode:"/>
<InlineUIContainer BaselineAlignment="Center">
<TextBox Text="{Binding OriginalPackage.BarcodeNumber}" />
</InlineUIContainer>
</TextBlock>
I was hoping setting IsEnabled="True" would fix it but it doesn't seem to.
The easy solution is to use a StackPanel with Orientation="Horizontal"

Copy Property to Clipboard

I have a string property in my ViewModel/Datacontext and want a simple button that copies its contents to the clipboard. Is this possible to do from XAML, or I do I need to handle the button click event (or use an ICommand) to accomplish this? I thought the following would work, but my button is always greyed out:
<Button Width="100" Content="Copy" Command="ApplicationCommands.Copy"
CommandTarget="{Binding MyStringProperty}"/>
The ApplicationCommands are expecting to be in a Toolbar or Menu which will give them FocusScope based on RoutedUICommands. If your button is outside a Toolbar or Menu, then you need to explicitly declare the focus scope:
<Button
Content="{Binding RelativeSource={RelativeSource Self}, Path=Command.Text}"
Command="ApplicationCommands.Copy"
FocusManager.IsFocusScope="True"/>
The CommandTarget is used to declare which element will provide the FocusScope which means that the Copy button will only be enabled whenever the element declared in the CommandTarget has focus, and in the case of copy, has text highlighted:
<Button
Content="{Binding RelativeSource={RelativeSource Self}, Path=Command.Text}"
Command="ApplicationCommands.Copy"
CommandTarget="{Binding ElementName=MyElement}" />
In answer to your specific question, you'd need to intercept the ApplicationCommands.Copy command to get/set your ViewModel's MyStringProperty; and to be honest, I'm not sure where to even start to figure that one out. Maybe someone smarter around here could provide that piece of the puzzle.

Getting a templated button's command to work

I've used a control template to change the appearance of a button in a trivial way. It now looks different, but does not behave like a button. There are really two problems:
The button's command is never executed
After clicking on the button, it appears selected (i.e., the ellipse turns into an ugly blue rectangle)
Here's the general idea:
<Button Command="{x:Static commands:...}"
CommandParameter="{Binding}">
<Button.Template>
<ControlTemplate TargetType="Button">
<Ellipse Fill="{Binding ...}"
.../>
</ControlTemplate>
</Button.Template>
</Button>
There's no reason this should be happening. I put together a test using ApplicationCommands.Copy and the command fired just fine. Could be your CommandBinding isn't working properly.
I also didn't see this based on copying your sample XAML and just setting Fill="Green". You can try setting FocusVisualStyle="{x:Null}" on the Button.
The problem turned out to be that Fill was bound to a value that could be null. If the Fill brush is null rather than transparent, then there's nothing to click and the command doesn't get executed. As Drew mentioned, with a solid fill, the button works correctly.
Takeaway lesson: if you want to hide your shape but still have it respond to user interaction, use a transparent brush, not a null brush.
I had a similar problem with a custom templated button:
<my:UniButton Command="{Binding MyCommand}"/>
The binding didn't work until adding a RelativeSource:
<my:UniButton Command="{Binding MyCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=my:CustomPanel}}"/>
where CustomPanel is a control where my button lies.
Withal I had a simple button on the same panel, but it worked fine even without RelativeSource.

Resources