I want when I press on bulb button every time picture will change. I tried but without success. My code doesn't work, please tell my why, thanks.
Here is the UserControl in XAML:
<UserControl x:Class="PL_Wpf.CustomControls.Bulb"
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:i="http://schemas.microsoft.com/expression/2010/interactivity"
mc:Ignorable="d"
>
<Grid>
<Button x:Name="BulbButton" Height="60" Width="40" Click="BulbButton_Click" >
<Button.Template>
<ControlTemplate>
<Image Source="../Pics/bulb_off.jpg" Width="40" Height="60" >
<Image.Style>
<Style TargetType="{x:Type Image}">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=Bulb, Path=OnOff}" Value="True">
<Setter Property="Source" Value="../Pics/bulb_on.jpg" />
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=Bulb, Path=OnOff}" Value="False">
<Setter Property="Source" Value="../Pics/bulb_off.jpg" />
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</ControlTemplate>
</Button.Template>
</Button>
</Grid>
</UserControl>
And here is the code behind:
public partial class Bulb : UserControl, INotifyPropertyChanged
{
public bool OnOff { get; set; }
public Bulb()
{
InitializeComponent();
DataContext = this;
OnOff = false;
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(PropertyChangedEventArgs e)
{
if (PropertyChanged != null)
{
PropertyChanged(this, e);
}
}
public void BulbButton_Click(object sender, RoutedEventArgs e)
{
OnOff = (OnOff == false) ? true : false;
}
public bool On
{
get { return OnOff; }
set
{
OnOff = value;
OnPropertyChanged(new PropertyChangedEventArgs("On"));
}
}
}
The think that you want to achieve with your control can be simply done by modifying the control template of a checkbox.
Just add this code in the window in place of your control:
<CheckBox>
<CheckBox.Template>
<ControlTemplate TargetType="CheckBox">
<Grid>
<Image Source="pack://siteoforigin:,,,/Pics/bulb_off.jpg" Width="40" Height="60" />
<Image Source="pack://siteoforigin:,,,/Pics/bulb_on.jpg" Width="40" Height="60" Name="CheckMark" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="false">
<Setter TargetName="CheckMark" Property="Visibility" Value="Hidden"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</CheckBox.Template>
</CheckBox>
Related
I have a MenuItem.
When I click the item, I want the sub-MenuItem to open and show a form to login.
Hereunder what I already made (feel free to completely redesign this)...
The problem now is:
when I mouse-over or click in the subitem, the item is highlighted.
when i click on an item (except the textbox) the menu closes.
Thank you for your help!
<MenuItem>
<MenuItem.Header>
<Image
Width="16"
Height="16">
<Image.Style>
<Style TargetType="{x:Type Image}">
<Setter Property="Source" Value="{StaticResource DisconnectedIcon}" />
<Style.Triggers>
<DataTrigger Value="True" Binding="{Binding Connected}">
<Setter Property="Source" Value="{StaticResource ConnectedIcon}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</MenuItem.Header>
<autogrid:AutoGrid
Columns="Auto,Auto"
Margin="1"
RowHeight="25">
<autogrid:AutoGrid.Resources>
<Style TargetType="{x:Type TextBox}">
<Setter Property="Margin" Value="3" />
<Setter Property="Width" Value="100" />
</Style>
<Style TargetType="{x:Type PasswordBox}">
<Setter Property="Margin" Value="3" />
<Setter Property="Width" Value="100" />
</Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Margin" Value="3" />
<Setter Property="Width" Value="100" />
</Style>
</autogrid:AutoGrid.Resources>
<TextBlock Text="System: "/>
<TextBox></TextBox>
<TextBlock Text="Username: "/>
<TextBox></TextBox>
<TextBlock Text="Password: "/>
<PasswordBox></PasswordBox>
</autogrid:AutoGrid>
<Button Content="Connect"/>
</MenuItem>
I recommend making your login controls part of a new window.
And for anyone else following along, you need to run Install-Package WpfAutoGrid -Version 1.4.0 in your package manager console.
For future reference, please post a MINIMAL and complete example.
Took me longer than it should have to throw this together.
Please read "How to create a Minimal, Complete, and Verifiable example"
Here's my MCVE example:
MainWindow.xaml:
<Window x:Class="WpfApp1.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"
xmlns:autogrid="clr-namespace:WpfAutoGrid;assembly=WpfAutoGrid"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="250" Width="500">
<Window.DataContext>
<local:VM/>
</Window.DataContext>
<DockPanel>
<Menu DockPanel.Dock="Top">
<MenuItem>
<MenuItem.Header>
<Image
Width="16"
Height="16">
<Image.Style>
<Style TargetType="{x:Type Image}">
<Setter Property="Source" Value="{StaticResource DisconnectedIcon}" />
<Style.Triggers>
<DataTrigger Binding="{Binding Connected}" Value="true">
<Setter Property="Source" Value="{StaticResource ConnectedIcon}"/>
</DataTrigger>
<DataTrigger Binding="{Binding Connected}" Value="false">
<Setter Property="Source" Value="{StaticResource DisconnectedIcon}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</MenuItem.Header>
<MenuItem x:Name="connectMenuItem" Header="{Binding ConnectOrDisconnect}" Click="MenuItem_Click"/>
</MenuItem>
</Menu>
<Grid DockPanel.Dock="Bottom" Background="Black" />
</DockPanel>
</Window>
MainWindow.xaml.cs:
using System.Windows;
namespace WpfApp1
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void MenuItem_Click(object sender, RoutedEventArgs e)
{
VM thisDC = (VM)this.DataContext;
if (thisDC.Connected)
{
// DisConnect
thisDC.Connected = false;
}
else
{
ConnectWindow cw = new ConnectWindow
{
Owner = this,
DataContext = this.DataContext
};
cw.ShowDialog();
}
}
}
}
ConnectWindow.xaml:
<Window x:Class="WpfApp1.ConnectWindow"
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"
xmlns:autogrid="clr-namespace:WpfAutoGrid;assembly=WpfAutoGrid"
mc:Ignorable="d" Title="ConnectWindow" Height="180" Width="270">
<autogrid:AutoGrid
Columns="Auto,Auto"
Rows="Auto,Auto, Auto, Auto"
Margin="20"
RowHeight="25">
<autogrid:AutoGrid.Resources>
<Style TargetType="{x:Type TextBox}">
<Setter Property="Margin" Value="3" />
<Setter Property="Width" Value="100" />
</Style>
<Style TargetType="{x:Type PasswordBox}">
<Setter Property="Margin" Value="3" />
<Setter Property="Width" Value="100" />
</Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Margin" Value="3" />
<Setter Property="Width" Value="100" />
</Style>
</autogrid:AutoGrid.Resources>
<TextBlock Text="System: "/>
<TextBox></TextBox>
<TextBlock Text="User Name: "/>
<TextBox></TextBox>
<TextBlock Text="Password: "/>
<PasswordBox></PasswordBox>
<Button Grid.ColumnSpan="2" Content="Connect" Click="Button_Click" />
</autogrid:AutoGrid>
</Window>
ConnectWindow.xaml.cs:
using System.Windows;
namespace WpfApp1
{
public partial class ConnectWindow : Window
{
public ConnectWindow()
{
InitializeComponent();
}
private bool verified = true;
private void Button_Click(object sender, RoutedEventArgs e)
{
if (verified)
{
VM thisDC = (VM)this.DataContext;
thisDC.Connected = true;
this.Close();
}
else
{
// error message
this.Close();
}
}
}
}
VM.cs:
using System.ComponentModel;
namespace WpfApp1
{
class VM : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private bool connected;
public bool Connected
{
get { return connected; }
set
{
{
connected = value;
OnPropertyChanged("Connected");
if (value) { ConnectOrDisconnect = "Disconnect"; }
else { ConnectOrDisconnect = "Connect"; }
}
}
}
private string connectOrDisconnect;
public string ConnectOrDisconnect
{
get { return connectOrDisconnect; }
set
{
connectOrDisconnect = value;
OnPropertyChanged("ConnectOrDisconnect");
}
}
public VM()
{
Connected = false;
}
protected void OnPropertyChanged(string name)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
}
App.xaml:
<Application x:Class="WpfApp1.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="resources.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
resources.xaml:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<BitmapImage x:Key="ConnectedIcon" UriSource="pack://application:,,,/WpfApp1;component/ConnectedIcon.ico" />
<BitmapImage x:Key="DisconnectedIcon" UriSource="pack://application:,,,/WpfApp1;component/DisconnectedIcon.ico" />
</ResourceDictionary>
I have an image that need to be showed based on condition, is that attachment file or not. The problem is, I've set trigger that set the value of the condition, but seems like the condition isn't work and the value always set to true.
<Image
Width="30"
Height="30"
Source="Resources/Images/chat_file_attach.png">
<Image.Style>
<Style TargetType="{x:Type Image}">
<Style.Triggers>
<DataTrigger Binding="{Binding AttachStat}" Value="False">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
<DataTrigger Binding="{Binding AttachStat}" Value="True">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
The question is. Is there any way to make the default value to false? I've set it to true on the C# looping data, whenever the condition is attachment included.
Take a look in your output window and search for:
System.Windows.Data Warning: 40 : BindingExpression path error
I think the AttachStat property is not available in the image's DataContext.
Use a single DataTrigger and make sure that the DataContext of the Image has a public AttachStat property:
<Image x:Name="img" Width="30" Height="30" Source="Resources/Images/chat_file_attach.png">
<Image.Style>
<Style TargetType="{x:Type Image}">
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger Binding="{Binding AttachStat}" Value="True">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
img.DataContext = new YourClass();
...
public class YourClass : INotifyPropertyChanged
{
private bool _attachStat;
public bool AttachStat
{
get
{
return _attachStat;
}
set
{
_attachStat = value;
NotifyPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
You can use a BoolToVisibilityConverter to convert a Boolean to and from a Visibility value.
In the resource section:
<BooleanToVisibilityConverter x:Key="BoolToVisibilityConverter" />
And the image:
<Image Width="30"
Height="30"
Source="Resources/Images/chat_file_attach.png"
Visibility="{Binding AttachStat,
Converter={StaticResource BoolToVisibilityConverter}}" />
In WPF I'm trying to create a "flag" control that displays a checkmark or an X based on a bound dependency property (Flag)
<UserControl x:Name="Root" (Other user control stuff)>
<ContentControl Height="20" x:Name="flagHolder">
<ContentControl.Style>
<Style TargetType="ContentControl">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=Root, Path=Flag}" Value="False">
<Setter Property="Content" Value="{StaticResource XIcon}" />
<Setter Property="Foreground" Value="Crimson"/>
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=Root, Path=Flag}" Value="True">
<Setter Property="Content" Value="{StaticResource CheckIcon}" />
<Setter Property="Foreground" Value="ForestGreen"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
</UserControl>
On startup every icon is correct (I have several of these controls, each bound to different values). However, when I toggle a few (one that was "off" turns "on" and the one currently "on" turns "off") I see two things:
The control that was turned "on" has become a green check (as desired)
The control that was turned "off" is now just blank
Inspecting the visual tree seems to indicate that everything is working (though I could easily be missing something here), and the order of the triggers doesn't seem to matter. What am I doing wrong?
Here is an example icon, the path geometry is removed since its just noise:
<Viewbox x:Key="CheckIcon" x:Shared="False">
<Path Style="{StaticResource IconPathStyle}">
<Path.Data>
<PathGeometry Figures="Bunch of SVG" FillRule="NonZero"/>
</Path.Data>
</Path>
</Viewbox>
I'm unable to reproduce your issue, but here what I have and it's working:
App.xaml
<Application x:Class="WpfApplication1.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources>
<Viewbox x:Key="CheckIcon" x:Shared="False">
<Canvas Height="24" Width="32">
<Path Width="7.85446" Height="8.57578" Canvas.Left="-0.0522281" Canvas.Top="-0.100391" Stretch="Fill" StrokeThickness="1.04192" StrokeMiterLimit="2.75" Stroke="#FF000000" Data="F1 M 0.468732,4.66838L 3.03345,7.95443L 7.28127,0.420569"/>
</Canvas>
</Viewbox>
<Viewbox x:Key="XIcon" x:Shared="False">
<Canvas Height="24" Width="32">
<Path Data="M0,0 L1,1 M0,1 L1,0" Stretch="Fill" Stroke="Black" StrokeThickness="3" Width="12" Height="12" />
</Canvas>
</Viewbox>
</Application.Resources>
</Application>
YesNo.xaml
<UserControl x:Class="WpfApplication1.YesNo" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Name="Root">
<ContentControl Height="20" Name="flagHolder">
<ContentControl.Style>
<Style TargetType="ContentControl">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=Root, Path=Flag}" Value="False">
<Setter Property="Content" Value="{StaticResource XIcon}" />
<Setter Property="Foreground" Value="Crimson"/>
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=Root, Path=Flag}" Value="True">
<Setter Property="Content" Value="{StaticResource CheckIcon}" />
<Setter Property="Foreground" Value="ForestGreen"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
</UserControl>
YesNo.xaml.cs
using System.Windows;
using System.Windows.Controls;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for UserControl1.xaml
/// </summary>
public partial class YesNo : UserControl
{
public YesNo()
{
InitializeComponent();
}
public static readonly DependencyProperty FlagProperty = DependencyProperty.Register(
"Flag", typeof(bool), typeof(YesNo), new PropertyMetadata(default(bool)));
public bool Flag {
get {
return (bool) GetValue(FlagProperty);
}
set {
SetValue(FlagProperty, value);
}
}
}
}
MainWindow.xaml
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wpfApplication1="clr-namespace:WpfApplication1"
xmlns:system="clr-namespace:System;assembly=mscorlib"
Title="" Width="400" Height="400">
<StackPanel Orientation="Vertical" Margin="50">
<wpfApplication1:YesNo Flag="{Binding Flag1}"/>
<wpfApplication1:YesNo Flag="{Binding Flag2}"/>
<wpfApplication1:YesNo Flag="{Binding Flag2}"/>
<wpfApplication1:YesNo Flag="{Binding Flag1}"/>
<Button Content="Toggle" Click="ButtonBase_OnClick"></Button>
</StackPanel>
</Window>
MainWindow.xaml.cs
public partial class MainWindow : INotifyPropertyChanged
{
private bool _flag1;
private bool _flag2;
public MainWindow()
{
InitializeComponent();
DataContext = this;
Flag1 = true;
Flag2 = false;
}
public bool Flag1 {
get {
return _flag1;
}
set {
_flag1 = value;
OnPropertyChanged();
}
}
public bool Flag2 {
get {
return _flag2;
}
set {
_flag2 = value;
OnPropertyChanged();
}
}
private void ButtonBase_OnClick(object sender, RoutedEventArgs e) {
Flag1 = !Flag1;
Flag2 = !Flag2;
}
}
How it looks like:
Video: http://www.screencast.com/t/J5IY7DR3Ry
I've following code in my WPF app.I'm trying to set the focus on a textbox on a button click...i.e. on invoking Check() method...
Code:
MainWindowResources.xaml
<Style TargetType="TextBox" x:Key="MyFiedlStyle">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=FocusOnMyField}" Value="true">
<Setter Property="FocusManager.FocusedElement" Value="{Binding ElementName=myField}"/>
</DataTrigger>
</Style.Triggers>
</Style>
MainWindow.xaml
<TextBox HorizontalAlignment="Left" Margin="1,1,0,0" Width="180" Text="{Binding MyAttributes.MyFieldValue}" TabIndex="4" Grid.Row="3" VerticalAlignment="Top" Grid.Column="5"
Name="myField" Style="{DynamicResource MyFieldStyle}"/>
MainWindowViewModel
private bool FocusOnMyField
{
get { return m_FocusOnMyField; }
set
{
m_FocusOnMyField = value;
OnPropertyChanged("FocusOnMyField");
}
}
private void Check()
{
this.FocusOnSecDescription = true;
}
Thanks.
I have a circle button below
<Button x:Name="btnLight" Width="72" Height="72" Content="" Margin="180,0,372,94" VerticalAlignment="Bottom" d:LayoutOverrides="VerticalAlignment">
<Button.Template>
<ControlTemplate>
<Grid>
<Ellipse>
<Ellipse.Fill>
<ImageBrush ImageSource="Images/light-off.jpg"/>
</Ellipse.Fill>
</Ellipse>
</Grid>
</ControlTemplate>
</Button.Template>
</Button>
How do I change the background image (Images/light-on.jpg) when I click it?
Thank you!
Wow! You have been given some complicated answers here... you're all doing too much work!!! This question has a really simple solution. First, let's sort out this ControlTemplate the way it should be:
<Button x:Name="btnLight" Width="72" Height="72" Content="" Margin="180,0,372,94"
VerticalAlignment="Bottom">
<Button.Template>
<ControlTemplate>
<Ellipse Name="Ellipse" Fill="{TemplateBinding Background}" />
</ControlTemplate>
</Button.Template>
</Button>
Now, you can add a really simple Style to perform your image change:
<Style TargetType="{x:Type Button}">
<Setter Property="Button.Background">
<Setter.Value>
<ImageBrush ImageSource="Images/Add_16.png" />
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="Button.IsPressed" Value="True">
<Setter Property="Button.Background">
<Setter.Value>
<ImageBrush ImageSource="Images/Copy_16.png" />
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
To do it properly you need to create a view model that contains a handler for the button to call when it's pressed and a boolean property you can use for a datatrigger to change the image. Start with the view model:
public class ViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public RelayCommand OnClickedCommand { get; private set; }
private bool _ImageChanged;
public bool ImageChanged
{
get { return this._ImageChanged; }
private set {
this._ImageChanged = value;
OnPropertyChanged("ImageChanged");
}
}
public ViewModel()
{
this.OnClickedCommand = new RelayCommand(param => OnClicked());
}
private void OnClicked()
{
this.ImageChanged = true;
}
}
Now create an instance of it and set it as your button's data context. Your button XAML should looks something like this:
<Button x:Name="btnLight" Margin="148,0,372,63" VerticalAlignment="Bottom" Command="{Binding OnClickedCommand}" Height="69">
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid>
<Ellipse>
<Ellipse.Fill>
<ImageBrush ImageSource="image1.png"/>
</Ellipse.Fill>
</Ellipse>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding ImageChanged}" Value="True">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid>
<Ellipse>
<Ellipse.Fill>
<ImageBrush ImageSource="image2.png"/>
</Ellipse.Fill>
</Ellipse>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>