Disable Content of Button WPF - wpf

I have a simple override of the Control Template for a button in WPF that looks like this.
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<Rectangle x:Name="ButtonRectangle" Fill="{StaticResource BlueBrush}"/>
<ContentPresenter Panel.ZIndex="1"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Grid>
</ControlTemplate>
Typically the button will contain text "OK", "Cancel", etc. If the button is ever disabled I want the text Foreground property to update to a disabled text style. I haven't found any way to let the content in the content presenter know that it is disabled. Where am I going wrong with this one?

Related

Strange border still resding on button; even after modifying the control template

I have a 'feedback' button which has this strange border:
So I searched online for some solutions and modified the control template, and I got this:
Control Template code:
<Button.Template>
<ControlTemplate TargetType="Button">
<ContentPresenter Content="{TemplateBinding Content}" />
</ControlTemplate>
</Button.Template>
So even after modifying the control template - I am getting a strange brown border. Help would be appreciated regarding this.
Button code:
<Button Grid.Row="3"
Grid.Column="2"
Grid.RowSpan="2"
Style="{StaticResource IconStyleBase}"
Name="Feedback_Button">
<Button.Template>
<ControlTemplate TargetType="Button">
<ContentPresenter Content="{TemplateBinding Content}" />
</ControlTemplate>
</Button.Template>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="218*" />
<RowDefinition Height="68*" />
</Grid.RowDefinitions>
<!--Icon-->
<Button Background="#3767B0"
Style="{StaticResource IconStyleContent}">
<!--Content-->
<Button.ContentTemplate>
<DataTemplate>
<Viewbox>
<TextBlock Padding="55"></TextBlock>
</Viewbox>
</DataTemplate>
</Button.ContentTemplate>
</Button>
<!--Icon Text-->
<Button Background="#FF2D5BA0"
Style="{StaticResource IconStyleSubBase}">
<!--Content-->
<Button.ContentTemplate>
<DataTemplate>
<Viewbox>
<TextBlock Padding="15">Feedback</TextBlock>
</Viewbox>
</DataTemplate>
</Button.ContentTemplate>
</Button>
</Grid>
</Button>
A DataTemplate defines the appearance of the the items that you set as Content of a button, but the button itself as a container has a default style and control template that defines how it looks like, along with its different states like mouse-over or pressed. That is where the border comes from.
You can try to create a style that sets the BorderThickness to 0 and apply it on each of your buttons. This approach works for control templates that bind the border thickness from their templated parent.
<Style x:Key="BorderlessButtonStyle" TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="BorderThickness" Value="0"/>
</Style>
If this does not work or you want adapt the appearance of your buttons in detail, you have to extract and adapt the button style and control template.
Your custom control template does not work, because you did not apply it to the inner buttons and you should remove Content="{TemplateBinding Content}". Nevertheless, your button control template does not define any control states, so it will not be responsive at all.
You should copy the control template for Button from here, or extract it manually via Blend or Visual Studio. Then you can remove or the Border within it, change its thickness or color, so it will disappear. Moreover, you can adapt its various states to fit your desired style.
A notice on your design. It do not think that it is a good idea to nest buttons. Your control should either be a single button or a panel with two buttons in it, but that also only makes sense if they execute different actions in a related context, like split buttons do.

How to set foreground and background colors on a WPF Menu control?

I've been working in WPF for quite a while, but there's something basic about styling that I just don't get.
How can I set the foreground and background colors for a Menu control? I started with this:
<Menu IsMainMenu="True" Background="#FF3A3A3A" Foreground="White">
<MenuItem Header="_File">
<MenuItem Header="_Exit">
</MenuItem>
</MenuItem>
</Menu>
The foreground color is apparently inherited by the MenuItem, but the background is not. Next attempt:
<Menu IsMainMenu="True" Background="#FF3A3A3A" Foreground="White">
<MenuItem Background="#FF3A3A3A" Header="_File">
<MenuItem Header="_Exit">
</MenuItem>
</MenuItem>
</Menu>
Now the highlight/overlay colors aren't right when the menu is activated, and I don't see an obvious property to set them. In addition, the menu popup has a wide, white border, and I don't see how to change it's color (or size), either.
What am I missing?
You will want to learn more about templates and styles in WPF (XAML really). In XAML, how a control looks and how a control operates are two completely different things. In your example, you may have a Foreground and Background property, but the style\template of the control my not utilize these properties for the display of the control.
Read http://wpftutorial.net/Templates.html and http://wpftutorial.net/TemplatesStyles.html, they will give you a good and quick overview. For a more in depth look, read this: http://msdn.microsoft.com/en-us/library/ee230084.aspx
If you are using Visual Studio 2012 to edit your WPF UI, you can easily create a copy of the style\template the menu control is using, and then edit it. If you are using Visual Studio 2010, you should download and install (it may or may not be free) Expression Blend to edit your XAML UI.
Tip: If you are using Visual Studio 2012, make sure your Document Outline window pane is visible all the time. This is very handy for editing a XAML UI. Mine defaulted to being collapsed on the left side of the program. This pane is visible in Expression Blend by default.
Find the MenuItem control in the Document Outline. Right-click on it and select Edit Template->Edit a Copy...
This will create a copy of the existing look-and-feel of the menu item for you to edit. When you do this, you will be in editing mode of that template, to "pop out" of that mode, click on the little icon on the top left of the Document Outline window.
When editing the template, you can see the layout and design of the template. When a menu item is being as the drop-down part, it's really displayed like a Popup menu (right click menu). Looking through that template, what pops out at me right away is this color resource named SubMenuBackgroundBrush:
<SolidColorBrush x:Key="SubMenuBackgroundBrush" Color="#FFF5F5F5"/>
If you do a search for SubMenuBackgroundBrush you can see that it is used on a part named PART_Popup:
<Popup x:Name="PART_Popup" AllowsTransparency="true" Focusable="false" HorizontalOffset="1" IsOpen="{Binding IsSubmenuOpen, RelativeSource={RelativeSource TemplatedParent}}" PopupAnimation="{DynamicResource {x:Static SystemParameters.MenuPopupAnimationKey}}" Placement="Bottom" VerticalOffset="-1">
<Themes:SystemDropShadowChrome x:Name="Shdw" Color="Transparent">
<Border x:Name="SubMenuBorder" BorderBrush="#FF959595" BorderThickness="1" Background="{StaticResource SubMenuBackgroundBrush}">
<ScrollViewer x:Name="SubMenuScrollViewer" Margin="1,0" Style="{DynamicResource {ComponentResourceKey ResourceId=MenuScrollViewer, TypeInTargetAssembly={x:Type FrameworkElement}}}">
<Grid RenderOptions.ClearTypeHint="Enabled">
<Canvas HorizontalAlignment="Left" Height="0" VerticalAlignment="Top" Width="0">
<Rectangle x:Name="OpaqueRect" Fill="{StaticResource SubMenuBackgroundBrush}" Height="{Binding ActualHeight, ElementName=SubMenuBorder}" Width="{Binding ActualWidth, ElementName=SubMenuBorder}"/>
</Canvas>
<Rectangle Fill="#F1F1F1" HorizontalAlignment="Left" Margin="1,2" RadiusY="2" RadiusX="2" Width="28"/>
<Rectangle Fill="#E2E3E3" HorizontalAlignment="Left" Margin="29,2,0,2" Width="1"/>
<Rectangle Fill="White" HorizontalAlignment="Left" Margin="30,2,0,2" Width="1"/>
<ItemsPresenter x:Name="ItemsPresenter" KeyboardNavigation.DirectionalNavigation="Cycle" Grid.IsSharedSizeScope="true" Margin="2" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" KeyboardNavigation.TabNavigation="Cycle"/>
</Grid>
</ScrollViewer>
</Border>
</Themes:SystemDropShadowChrome>
</Popup>
This is the popup that you see when you right-click on something that shows a menu, or a dropdown menu. Change the references from: {StaticResource SubMenuBackgroundBrush} to {TemplateBinding Foreground}.
When you run the program, you'll see that the main background of the popup has changed, but the area where the icon is displayed has not. These are all the <Rectangle Fill=" items in the popup control too. Change those also. The last reference to Rectangle looks like its the line splitting the icon and the text, you may not what to change that.
Enjoy the wonderful world of templates. It looks confusing and like a lot of work. It is. But when you get the hang of it, it's a very cool system. It's hard to go back to any other UI system after you get the hang of it.
What am I missing?
Controls are more or less customizable, and there are two levels of customizing a control:
Setting properties like Foreground, Background, etc, in the XAML where you place the control.
Setting the Template in your Style for the control, and creating your own ControlTemplate.
The second is more involved, but it offers much more flexibility in making the control look how you want. If this case, it sounds like that's what you'll need. Check out the default ControlTemplate for Menu and MenuItem. You can copy/paste them and modify as needed.
<Window.Resources>
<Style TargetType="{x:Type Menu}">
<Setter Property="Template">
<ControlTemplate TargetType="{x:Type Menu}">
<!-- your modified template here -->
</ControlTemplate>
</Setter>
</Style>
<Style TargetType="{x:Type MenuItem}">
<Setter Property="Template">
<ControlTemplate TargetType="{x:Type MenuItem}">
<!-- your modified template here -->
</ControlTemplate>
</Setter>
</Style>
</Window.Resources>

Binding the button Content to the userControl Content

I have some userControl that contain simple button.
I want to bind the button Content to the userControl Content - How to do it?
Set a name for the user control (for example x:Name="self") and in the Button
<Button Content={Binding ElementName=self}" />
Do you mean this or something else?
If the Button is inside the UserControl it is part of the UserControl's Content and can't recursively contain itself. The whole purpose of a UserControl is that you're explicitly defining a fixed set of Content. If you want variable Content then you should use a templated ContentControl something like this:
<ContentControl Content="{Binding SomeVariableValue}">
<ContentControl.Template>
<ControlTemplate TargetType="{x:Type ContentControl}">
<Border>
<!-- Other content from your user control -->
<Button Content="{TemplateBinding Content}"/>
</Border>
</ControlTemplate>
</ContentControl.Template>
</ContentControl>

WPF Changing text in a controltemplate at run time

I am making a template control so that I can have a button with an image that changes when you click it. I also am trying to get text on top of the button that can change at run time. I have the button images and everything working but I can't seem to get that label at runtime so I can change the text. Here is the code in the xaml. I am missing the code behind
<UserControl.Resources>
<ControlTemplate TargetType="{x:Type Button}" x:Key="ActionButton">
<Grid>
<Label Panel.ZIndex="2" HorizontalAlignment="Center" VerticalAlignment="Center" FontFamily="Arial" Name="lblText" Foreground="#5E4421" FontWeight="Bold" FontSize="14">Test</Label>
<Image Name="Normal" Source="/AssaultWare.Controls;component/Replayer/Images/button_off.png"/>
<Image Name="Pressed" Source="/AssaultWare.Controls;component/Replayer/Images/button_on.png"/>
<Image Name="Disabled" Source="/AssaultWare.Controls;component/Replayer/Images/button_off.png" Visibility="Hidden"/>
</Grid>
<ControlTemplate.Triggers>
...
</ControlTemplate.Triggers>
</ControlTemplate>
</UserControl.Resources>
<Button Canvas.Left="471" Canvas.Top="465" Template="{StaticResource ActionButton}" Name="btnRight"/>
Difficult to decipher your question, but I think you just need to change the Label to a ContentControl and bind its Content property to the Button's Content property:
<ContentControl Content="{TemplateBinding Content}" .../>

How to change the style of a combobox to a label or hyperlink in WPF?

I want to change the style of a combo box control to look like a hyperlink.
When user clicks on the hyperlink ( combo box) it show options in the combobox to select.
The idea is that I want combo box control to display as a plain text ( more readable form).
If anybody created this type of sytle please let me know.
You could edit the ComboBox template and replace the ContentPresenter with a Hyperlink-style button. This should work pretty well, and it is just a bit of XAML coding. You can find the original ComboBox template here, or using Expression Blend.
EDIT:
OK, well, you have a ComboBox template which looks something like this (extremely simplified!):
<ControlTemplate TargetType="{x:Type ComboBox}">
<Grid>
<!-- The popup that is displayed after you clicked on the ComboBox. -->
<Popup IsOpen="{TemplateBinding IsDropDownOpen}"
Placement="Bottom"/>
<!-- The button that is used to open the drop down. -->
<ToggleButton x:Name="btnOpenDropDown"
IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"/>
<!-- The control which displays the currently selected item. -->
<ContentPresenter x:Name="contentPres"
Content="{TemplateBinding SelectionBoxItem}"/>
</Grid>
</ControlTemplate>
Actually, it is a bit more complicated because the ToggleButton must occupy the whole width (since the drop down should open whereever you click on the ComboBox), but it should display only on the right of the content. However, for your scenario, we can neglect this since you will not have a drop down button.
Now, since you only want to display the content as a hyperlink and no button besides it, you no longer need a distinction between ContentPresenter and ToggleButton. Therefore, instead of using a separate ContentPresenter, you could use the ToggleButton to present the content since it also has a Content property. Something like that:
<ControlTemplate TargetType="{x:Type ComboBox}">
<Grid>
<!-- The popup that is displayed after you clicked on the ComboBox. -->
<Popup IsOpen="{TemplateBinding IsDropDownOpen}"
Placement="Bottom"/>
<!-- The button that is used to open the drop down AND to display the content (now). -->
<ToggleButton x:Name="btnOpenDropDown"
Content="{TemplateBinding SelectionBoxItem}"
IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"/>
</Grid>
</ControlTemplate>
Of course, there are some additional properties to move from the ContentPresenter to the ToggleButton.
Now, all you have to do is define another template for the ToggleButton which looks like a Hyperlink (and then assign this template to the ToggleButton above). Actually, this should not be difficult assuming that your content is always a string (again, simplified!):
<Style x:Key="hyperlinkButtonStyle" TargetType="{x:Type ButtonBase}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<TextBlock Text="{TemplateBinding Content}"
TextDecorations="Underline"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
This simplified code shows how you could do it. There are certainly other ways, and it still involves some work for you as the example was simplified. However, I cannot offer you the complete code.

Resources