Reputation: 1068
I am trying to change the Opacity
of the main application window through a settings window popup in real time. What is the proper way of doing this?
So far, I have tried using a Slider
to output the value to the settings file. When the settings popup is closed, the main window refreshes its opacity property based on the settings file. This method works but I'd like the ability to change the opacity and view the result in real time.
The second method I tried was using a Style
and applying it to the MainWindow. Then on slider move, the style would be overridden with the value from the slider. This works in real time. But for whatever reason, the settings popup window opacity is also affected even though no style is applied to it.
Here is a sample project named OpacityTest
with a main window, a button to open settings popup and slider to control the program's opacity.
App.xaml:
<Application x:Class="OpacityTest.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="Window" x:Key="wrapper">
<Setter Property="OverridesDefaultStyle" Value="false"/>
<Setter x:Name="opacitySetter" Property="Opacity" Value="1"/>
</Style>
</Application.Resources>
</Application>
MainWindow.xaml:
<Window x:Class="OpacityTest.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" Style="{DynamicResource wrapper}" Background="#FFCDCDCD" AllowsTransparency="True" WindowStyle="None">
<Grid>
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<Button Content="Settings" HorizontalAlignment="Center" VerticalAlignment="Center" Width="75" Click="Button_Click"/>
</StackPanel>
</Grid>
</Window>
New window labeled Settings, Settings.xaml:
<Window x:Class="OpacityTest.Settings"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Settings" Height="300" Width="300">
<Grid>
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<Slider x:Name="ChangeTransparency" MinWidth="138" MinHeight="22" VerticalAlignment="Center" Padding="0" Orientation="Horizontal" HorizontalAlignment="Center" Value="1" Minimum=".05" Maximum="1" LargeChange=".01" SmallChange=".01" TickFrequency="100" IsSnapToTickEnabled="False" MouseMove="ChangeTransparency_MouseMove"/>
</StackPanel>
</Grid>
</Window>
MainWindow.xaml.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace OpacityTest
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Settings settings = new Settings();
settings.ShowDialog();
}
}
}
Settings.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace OpacityTest
{
/// <summary>
/// Interaction logic for Settings.xaml
/// </summary>
public partial class Settings : Window
{
public Settings()
{
InitializeComponent();
}
private void ChangeTransparency_MouseMove(object sender, MouseEventArgs e)
{
Style style = new Style { TargetType = typeof(Window) };
style.Setters.Add(new Setter(OpacityProperty, Opacity = ChangeTransparency.Value));
Application.Current.Resources["wrapper"] = style;
}
}
}
Upvotes: 2
Views: 430
Reputation: 56556
It looks like your Style
is behaving as if it were declared in a XAML file in a way that affects all Window
s, not just the wrapper
style, e.g.
<Style TargetType="Window"> ... </Style>
Instead of:
<Style TargetType="Window" x:Key="wrapper"> ... </Style>
I'm not immediately sure of how to declare it the way you're trying to, but a much easier way to accomplish what you're trying to do is to put this in MainWindow.xaml.cs:
private void Button_Click(object sender, RoutedEventArgs e)
{
Settings settings = new Settings();
this.SetBinding(OpacityProperty,
new Binding("Value") { Source = settings.ChangeTransparency });
settings.ShowDialog();
}
No handler on ChangeTransparency
is required this way. The only reason I might consider modifying the Style
instead is if you can have multiple MainWindow
s at once, and want one Settings
window (opened from any of them) to control them all at once.
As an aside, if you do find that you need to attach to ChangeTransparency
, you should attach a handler to its ValueChanged
event instead of MouseMove
(while MouseMove
will generally work out, it's really not the same; e.g. for keyboard input, only ValueChanged
will fire).
If Settings
can be used from other windows and/or has more properties, you might wish to change Settings
to take a Window
(or other type) in its constructor, and set up the binding(s) there instead, to keep your code/logic centralized and clean.
Upvotes: 3