I want all textboxes in my application to have a dark grey background when they are disabled or read only. I have added a style to my App.xaml which I believe should apply the style throughout my app.
App.xaml:
<Application x:Class="XXXX.Deployment.Utils.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:XXXX.Deployment.Utils" >
<Application.Resources>
<local:InvertBoolConverter x:Key="invertBoolConverter" />
<Style TargetType="TextBox" >
<Style.Triggers>
<Trigger Property="IsReadOnly" Value="True">
<Setter Property="Background" Value="DarkGray" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Background" Value="DarkGray" />
</Trigger>
</Style.Triggers>
</Style>
</Application.Resources>
The style is applying in the design window but not when I actually run the application. I created a window with just a single textbox and set the IsEnabled property to False so I am not sure why this style would not be applied.
TestWindow.xaml:
<Window x:Class="XXXX.Deployment.Utils.TestWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:XXXX.Deployment.Utils"
mc:Ignorable="d"
Height="200" Width="800">
<StackPanel>
<TextBox Margin="2" IsEnabled="False" />
</StackPanel>
TestWindow.xaml.cs:
namespace XXXX.Deployment.Utils
{
public partial class TestWindow : Window
{
public TestWindow()
{
InitializeComponent();
}
}
}
I launch the window from within a console application and use
TestWindow t = new TestWindow();
t.ShowDialog();
EDIT
I think this issue may be because the App.xaml build action is not 'ApplicationDefinition'. We have all our UI in a common utility class library so we get the error 'Library project file cannot specify ApplicationDefinition element'. Is it possible for us to have a global style for controls even if our UI is in a class library?
Related
I'm wondering why setting background color of a grid in application resources results in whole window covered by grid background, even if I don't have grid panel specified in XAML main window file.
MainWindow.xaml:
<Window x:Class="TicTacToe.DesktopApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="Tic-tac-toe"
Height="420"
Width="420"
ResizeMode="NoResize"
WindowStyle="SingleBorderWindow">
<DockPanel>
<Button Content="Button"></Button>
</DockPanel>
</Window>
App.xaml:
<Application x:Class="TicTacToe.DesktopApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources>
<Style TargetType="Button">
<Setter Property="Margin" Value="10" />
</Style>
<Style TargetType="Grid">
<Setter Property="Background" Value="Red" />
<!--Uncomment the line below to see that button seems to be hidden under the grid.-->
<!--<Setter Property="Opacity" Value="0.5" />-->
</Style>
</Application.Resources>
</Application>
MainWindow.xaml.cs and App.xaml.cs contain only auto generated code. Nothing special.
Visual Studio preview shows window as expected:
Instead of it I'm getting:
Questions
Why it behaves like that? Is there somewhere hidden and always present grid that overlays whole window and gets included by my styling rules? And if so, why it does and why it is applied with the observable delay of a fragment of a second?
That is a grid used by the Visual tree design tools to select elements in the visual tree when debugging. You can verify this using an event setter,and clicking the grid, or by running the app, not in debug mode.
<Style TargetType="Grid">
<Setter Property="Background" Value="Red" />
<EventSetter Event="PreviewMouseDown" Handler="Grid_PreviewMouseDown"/>
<!--Uncomment the line below to see that button seems to be hidden under the grid.-->
<!--<Setter Property="Opacity" Value="0.5" />-->
</Style>
,
public partial class App : Application
{
private void Grid_PreviewMouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
MessageBox.Show(VisualTreeHelper.GetParent(sender as Grid).ToString());
}
}
I'm in the making of a usercontrol library. Therefore I don't have app.xaml file nor mainwindow.xaml.
I imported (copied) a slider style from another WPF project. This resource dictionary is set to page and was working fine before but, as soon as I apply it to my slider then the control is not showing in VisualStudio as well as runtime. No errors are thrown.
<UserControl x:Class="WPF.UserControls.CustomSlider"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WPF.UserControls"
x:Name="CustomSliderControl"
mc:Ignorable="d"
d:DesignHeight="407" d:DesignWidth="127">
<UserControl.Resources>
<ResourceDictionary Source="/WPFUserControls;component/Styles/BaseSliderStyle.xaml"/>
</UserControl.Resources>
<Grid>
<Slider x:Name="Hello" Style="{DynamicResource BaseSliderStyle}" Value="{Binding Value, Mode=TwoWay,
RelativeSource={RelativeSource AncestorType={x:Type local:CustomSlider}}}" Minimum="0.0" Maximum="1.0"/>
</Grid>
And here is part of the slider style :
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WPF.UserControls">
<Style x:Key="BaseSliderStyle" TargetType="{x:Type Slider}">
<Setter Property="Stylus.IsPressAndHoldEnabled" Value="false"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="Foreground" Value="{StaticResource SliderThumb.Static.Foreground}"/>
<Setter Property="Template" Value="{StaticResource SliderHorizontal}"/>
<Style.Triggers>
<Trigger Property="Orientation" Value="Vertical">
<Setter Property="Template" Value="{StaticResource SliderVertical}"/>
</Trigger>
</Style.Triggers>
</Style>
I may have miss something. Any hint ?
Thanks.
Make sure that you have added a reference to WPFUserControls.dll and try this:
<UserControl ...>
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/WPFUserControls;component/Styles/BaseSliderStyle.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Grid>
<Slider x:Name="Hello" Style="{StaticResource BaseSliderStyle}" Value="{Binding Value, Mode=TwoWay,
RelativeSource={RelativeSource AncestorType={x:Type local:CustomSlider}}}" Minimum="0.0" Maximum="1.0"/>
</Grid>
</UserControl>
Since I am using the StaticResource markup extension you should get an exception if the "BaseSliderStyle" cannot be found. You can switch back to using DynamicResource when you have confirmed that the style is found and is being applied as expected.
Also note that I am using a merged ResourceDictionary and a pack URI to specify the source: https://msdn.microsoft.com/en-us/library/aa970069(v=vs.110).aspx.
Please also make sure that that the resource dictionary is actually called "BaseSliderStyle.xaml" and that is located under a folder called "Styles" at the root of the project/assembly called "WPFUserControls".
I'm totally new on WPF and I need your help for creating a wpf custom ListBox with scrollbar wider than the default.
I've found a solution that works fine for a Window WPF including a ListBox:
<Window x:Class="iFixCustomControlsTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:cc="clr-namespace:iFixCustomControls;assembly=iFixCustomControls"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
Title="MainWindow" Height="350" Width="525">
<Grid>
<ListBox HorizontalAlignment="Left" Height="92" Margin="56,88,0,0" VerticalAlignment="Top" Width="357" ScrollViewer.VerticalScrollBarVisibility="Visible"/>
</Grid>
<Window.Resources>
<Style TargetType="ScrollBar">
<Setter Property="Width" Value="100"/>
</Style>
</Window.Resources>
</Window>
This solution is not the my favorite one, because it implies to write code in a Window including a "classic" Listbox. What I need is a way to modify scrollbar inside the Listbox (if I understood fine) in Generic.xaml:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:iFixCustomControls">
<Style TargetType="local:iFixCustomListBox" BasedOn="{StaticResource {x:Type ListBox}}">
<!--
Setting scrollbar wider than default
Something like:
<Style TargetType="ScrollBar">
<Setter Property="Width" Value="100"/>
</Style>
-->
</Style>
</ResourceDictionary>
.cs file is:
public class iFixCustomListBox : ListBox
{
static iFixCustomListBox()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(iFixCustomListBox), new FrameworkPropertyMetadata(typeof(iFixCustomListBox)));
}
}
Is this approach correct or a better way should involve User Control instead Custom Controls?
If I understand you correctly you have a custom control type derived from ListBox and you want every instance of that control to have a wider vertical scrollbar.
If so, you can just use a custom style for your control (which you probably have already), and add a ScrollBar style to that style's Resources collection:
<Style TargetType="{x:Type local:iFixCustomListBox}">
<Style.Resources>
<Style TargetType="{x:Type ScrollBar}">
<Setter Property="Width" Value="100" />
</Style>
</Style.Resources>
</Style>
I tried with this style placed in the resources collection of (a) a window, and (b) the application, and it worked fine in both cases, so I assume it would also work if placed in generic.xaml.
What about this?
<ScrollViewer Width="100">
<ListBox ...>
</ScrollViewer>
I've got a UserControl that contains a button:
<Button Content="Button"/>
And a style:
<Style TargetType="Button">
<Setter Property="Background" Value="Blue"/>
</Style>
The parent window (or another UserControl) may set another more general style:
<Style TargetType="Button">
<Setter Property="Background" Value="Red"/>
</Style>
The result is (what is obvious) that parent buttons will have more general style (Red) and my user control will have buttons with more specific style (Blue).
I'm wondering how to invert such behaviour in order to achieve something like setting the default style in my custom user control which could be then overriden in parent control or window if necessary?
The key is, that default style is defined first in custom user control and it is overriden automaticly by its parent. That is way I called it an inversion.
The imaginary example of the solution maight look like the following:
<Style TargetType="Button" StylePriority="Default">
<Setter Property="Background" Value="Blue"/>
</Style>
The StylePriority could indicate that if there is no other style defined for that button, then the default style should be applied to it.
You could use dynamic resources.
A UserControl:
<UserControl x:Class="Example.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Example">
<UserControl.Resources>
<Style TargetType="local:UserControl1">
<Style.Resources>
<Style TargetType="Button" x:Key="UserControl1.DefaultButtonStyle">
<Setter Property="Background" Value="Red"/>
</Style>
</Style.Resources>
</Style>
</UserControl.Resources>
<Button Content="UserControlButton" Style="{DynamicResource UserControl1.DefaultButtonStyle}"/>
</UserControl>
And a Window:
<Window x:Class="Example.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Example">
<Window.Resources>
<Style TargetType="Button">
<Setter Property="Background" Value="Blue" />
</Style>
</Window.Resources>
<StackPanel>
<local:UserControl1 >
<local:UserControl1.Resources>
<Style x:Key="UserControl1.DefaultButtonStyle" TargetType="Button"
BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="FontSize" Value="40" />
</Style>
</local:UserControl1.Resources>
</local:UserControl1>
<Button Content="WindowButton" />
</StackPanel>
</Window>
If you remove the style for the control in the window, the default user control button style will be applied.
Create a dependency property in your UserControl for the buttons colour, and then bind to it. You can specify a default value of blue for that property.
public static readonly DependencyProperty ButtonColorProperty =
DependencyProperty.Register("ButtonColor", typeof(Color), typeof(MyUserControl),
new PropertyMetadata(Colors.Blue));
public Color State
{
get { return (Color)this.GetValue(ButtonColorProperty); }
set { this.SetValue(ButtonColorProperty, value); }
}
<UserControl ...
x:Name="root">
<Button Content="Button" Background="{Binding ElementName=root, Path=ButtonColor}" />
</UserControl>
Then set that property to red where you want to use the UserControl.
<local:MyUserControl ButtonColor="Red" />
I have a simple toggle button which works perfectly well . I can click on the toggle button and change the image that it shows . What i now want to do is the same thing from the code behind . Found a link that is similar
EDIT : This is what i want to do
I read up on the following thread that tells exactly what i need to do
WPF ToggleButton.IsChecked binding does not work
Programmatically my code does not seem to have any effect . if i click on the UI it works but i really wanna change state from within the program . The below program is just a prototype .
I cant figure out whats wrong in my XAML or code . Finnally decided to paste all of it as it a test program !
Xaml :
<Window x:Class="ToggleButtonImageChange.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ToggleButtonImageChange"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Image Source="secured.jpg"
x:Key="MyImage1" />
<Image Source="unsecured.jpg"
x:Key="MyImage2" />
<Style TargetType="{x:Type ToggleButton}"
x:Key="MyToggleButtonStyle">
<Setter Property="Content"
Value="{DynamicResource MyImage2}" />
<Style.Triggers>
<Trigger Property="IsChecked"
Value="True">
<Setter Property="Content"
Value="{DynamicResource MyImage2}" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<ToggleButton Style="{StaticResource MyToggleButtonStyle}" Name="tgbtn" Margin="0,29,0,139" IsChecked="{Binding Path=isAdmin, Mode=TwoWay}"/>
</Grid>
</Window>
Code behind :
namespace ToggleButtonImageChange
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window,INotifyPropertyChanged
{
bool _isAdmin;
public MainWindow()
{
InitializeComponent();
isAdmin = true;
OnPropertyChanged("isAdmin");
}
public bool isAdmin
{
get
{
return _isAdmin;
}
set
{
_isAdmin = value;
OnPropertyChanged("isAdmin");
}
}
private void OnPropertyChanged(string p)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(p));
}
public event PropertyChangedEventHandler PropertyChanged;
}
I went into the debugger and saw that even though i set isAdmin to true the button isChecked remains false and hence the incorrect image is displayed . I cant quite understand what wrong did do & how to get the isChecked changed through code .
Try to change the xaml file to this:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow"
Height="350" Width="525"
x:Name="TestWindow">
<Window.Resources>
<Image Source="secured.png" x:Key="MyImage1" />
<Image Source="unsecured.png" x:Key="MyImage2" />
<Style TargetType="{x:Type ToggleButton}" x:Key="MyToggleButtonStyle">
<Setter Property="Content" Value="{DynamicResource MyImage2}" />
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Content" Value="{DynamicResource MyImage1}" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<ToggleButton x:Name="tgbtn"
Margin="0,29,0,139"
Style="{StaticResource MyToggleButtonStyle}"
IsChecked="{Binding Path=isAdmin, Mode=TwoWay, ElementName=TestWindow}"/>
</Grid>
</Window>
Notice the default Content value use MyImage2, but the trigger set it to MyImage1 - they just need to be different images.
Also notice the x:Name="TestWindow" that I've add to root window element - it is used later in binding:
{Binding Path=isAdmin, Mode=TwoWay, ElementName=TestWindow}
This is basically all what is required to change to make it work as you expect, I believe.
Also you can leave you constructor in code behind like this, but this is optional changes:
public MainWindow()
{
InitializeComponent();
isAdmin = true;
}
Hope that helps.