How to bind method to a HoverButton? - wpf

I've been looking for hours but I can't find anything useful. Any help appreciated!
I'm writing a Kinect application using WPF with the Coding4Fun toolkit and the MVVM pattern.
I'd like to put all my kinect related logic in my ViewModel and bind those methods to a HoverButton (found in the C4F toolkit).
A normal button had the 'Command' property, However the HoverButton does not.
So in short:
I want to bind the click event of a HoverButton to a method in my ViewModel.
My XAML:
<Window x:Class="KinectTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:fun="clr-namespace:Coding4Fun.Kinect.Wpf.Controls;assembly=Coding4Fun.Kinect.Wpf" Title="MainWindow" Height="350" Width="525"
Loaded="WindowLoaded"
Closed="WindowClosed"
Cursor="None"
>
<Grid Name="MainGrid" MouseMove="GridHoverMouseMove" DataContext="_viewModel">
<Canvas Name="SkeletonCanvas" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Background="Black">
<fun:HoverButton Name="KinectUp" ImageSource="/Images/blue_glass.png" ActiveImageSource="/Images/blue_glass.png" ImageSize="100" Canvas.Top="26" TimeInterval="1000">
</fun:HoverButton>
<fun:HoverButton Name="KinectDown" ImageSource="/Images/red_glass.png" ActiveImageSource="/Images/red_glass.png" ImageSize="100" Canvas.Bottom="26" TimeInterval="1000"/>
</Canvas>
<Image Name="ColorImage" VerticalAlignment="Bottom" HorizontalAlignment="Right" Width="120" Height="120"></Image>
<TextBlock Name="Notification" Foreground="White" FontSize="50" VerticalAlignment="Top" HorizontalAlignment="Stretch" TextAlignment="Center" Text="{Binding Path=Notification, Mode=TwoWay}"></TextBlock>
<Canvas Name="CanvMouse" Background="Transparent" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<Image Name="imgMouse" Width="70" Source="/Images/handround_green.png"></Image>
</Canvas>
</Grid>
</Window>
My ViewModel:
internal class MainViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public ICommand KinectUpClick { get; private set; }
public ICommand KinectDownClick { get; private set; }
private string _notification = "Hello";
public SensorHelper SensorHelper { get; set; }
public string Notification
{
get { return _notification; }
set
{
_notification = value;
PropertyChanged(this, new PropertyChangedEventArgs("Notification"));
}
}
public MainViewModel()
{
KinectUpClick = new RelayCommand(PerformKinectUpClick, CanKinectUpClick);
KinectDownClick = new RelayCommand(PerformKinectDownClick, CanKinectDownClick);
}
private bool CanKinectUpClick(object parameter)
{
return SensorHelper.CanMoveUp;
}
private bool CanKinectDownClick(object parameter)
{
return SensorHelper.CanMoveDown;
}
private void PerformKinectUpClick(object parameter)
{
ThreadPool.QueueUserWorkItem((o) =>
{
Notification = "Kinect goes up!";
SensorHelper.MoveAngle(5);
Notification = "Kinect ready...";
});
}
private void PerformKinectDownClick(object parameter)
{
ThreadPool.QueueUserWorkItem((o) =>
{
Notification = "Kinect goes down!";
SensorHelper.MoveAngle(-5);
Notification = "Kinect ready...";
});
;
}
}
}
My Code-behind:
public partial class MainWindow : Window
{
private readonly MainViewModel _viewModel;
private SensorHelper _sensorHelper;
public MainWindow()
{
InitializeComponent();
_viewModel = new MainViewModel();
MainGrid.DataContext = _viewModel;
}
private void WindowLoaded(object sender, RoutedEventArgs e)
{
try
{
_sensorHelper = new SensorHelper();
}
catch (Exception exception)
{
MessageBox.Show(exception.Message);
}
_viewModel.SensorHelper = _sensorHelper;
_sensorHelper.InitializeSkeleton(ref SkeletonCanvas);
//_sensorHelper.CaptureMouse(CanvMouse);
_sensorHelper.InitializeColorFrame(ColorImage);
_sensorHelper.StartKinect();
}
private void WindowClosed(object sender, EventArgs eventArgs)
{
_sensorHelper.StopKinect();
}
private void GridHoverMouseMove(object sender, MouseEventArgs e)
{
imgMouse.SetValue(Canvas.LeftProperty, e.GetPosition(CanvMouse).X - imgMouse.ActualWidth/2);
imgMouse.SetValue(Canvas.TopProperty, e.GetPosition(CanvMouse).Y - imgMouse.ActualHeight/2);
MouseHelper.CheckButton(KinectUp, imgMouse);
MouseHelper.CheckButton(KinectDown, imgMouse);
}
}

Okay, very simple, what you'll have to do is bind an ICommand/Command to an Event by using an EventToCommand which can be found in the MVVMLight Toolkit.
You can use Blend for that as well
Simple example :
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:GalaSoft_MvvmLight_Command="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WPF4"
x:Class="TestProject.Window5"
x:Name="Window"
Title="Window5"
Width="640" Height="480">
<Grid x:Name="LayoutRoot">
<Button Content="Button" HorizontalAlignment="Left" Height="69" Margin="92,117,0,0" VerticalAlignment="Top" Width="206">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<GalaSoft_MvvmLight_Command:EventToCommand Command="{Binding Kinect.MyCommand, Source={StaticResource Locator}}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</Grid>
</Window>

Related

Caliburn Micro MVVM : How to subscribe and unsubscribe event in ViewModel?

I created a WPF sample (using caliburn micro with MVVM pattern, no code-behind) with a view model and their related views:
ShellView.xaml and ShellViewModel.cs
The ShellView contains:
A ComobBox, which contains a list of string, if this combox selection is changed, it will raise comboBox1_SelectionChanged() in ShellViewModel.
A Button, if click this button, it will raise Button1_Click() to delete the first item of list in ShellViewModel.
My questions:
If I want to click the button without trigger comboBox1_SelectionChanged in view model, how to do that?
If it implemented in code-behind, I can do like this:
public void Button1_Click(object sender, EventArgs e)
{
comboBox1.SelectionChanged -= comboBox1_SelectionChanged;
MyCollection.RemoveAt(0);
comboBox1.SelectionChanged += comboBox1_SelectionChanged;
}
I have no idea how to achieve this in view model. The following is the code:
ShellView.xaml
<UserControl x:Class="WpfApp.Views.ShellView"
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:WpfApp.Views"
xmlns:cal="http://caliburnmicro.com"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height=" auto"/>
<RowDefinition Height=" auto"/>
</Grid.RowDefinitions>
<ComboBox Name="comboBox1" Grid.Row="0" ItemsSource="{Binding MyCollection}" SelectedValue="{Binding SelectMyListValue}"
cal:Message.Attach="[Event SelectionChanged]=[Action comboBox1_SelectionChanged($source,$eventArgs)]" />
<Button Name="Button1" Grid.Row="1" Content="Delete"
cal:Message.Attach="[Event Click]=[Action Button1_Click($source,$eventArgs)]" />
</Grid>
</UserControl>
ShellViewModel.cs
using Caliburn.Micro;
using System;
using System.Windows.Controls;
namespace WpfApp.ViewModels
{
public class ShellViewModel : Conductor<object>.Collection.OneActive
{
private BindableCollection<string> _myCollection = new BindableCollection<string>() { "item1", "item2"};
public BindableCollection<string> MyCollection
{
get => _myCollection;
set
{
_myCollection = value;
NotifyOfPropertyChange(() => MyCollection);
}
}
private string _selectMyListValue = "item1";
public string SelectMyListValue
{
get => _selectMyListValue;
set
{
_selectMyListValue = value;
NotifyOfPropertyChange(nameof(SelectMyListValue));
}
}
public void comboBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
// Do something...
}
public void Button1_Click(object sender, EventArgs e)
{
MyCollection.RemoveAt(0);
}
}
}
Thank you in advance.
Your requirement can't be fully met, as when you remove the selected item from the collection a change of SelectedValue (to null) is inevitable.
Furthermore: You don't need to bind to the SelectionChanged event. You already have a binding to SelectedValue, so the setter of the bound property is called when the selection changes. This doesn't happen, when you remove a value from the collection that is not currently selected.
I would also recommend not to subscribe to the Clicked event of the button, but to bind an ICommand (added to your viewmodel) to the Command property of the button. An easy to use implementation would be the RelayCommand from the Windows Community Toolkit. You can read about it here: https://learn.microsoft.com/en-us/windows/communitytoolkit/mvvm/relaycommand. It also isn't difficult to implemnt a version on your own, if you don't want to use the whole toolkit.
Code sample:
public class RelayCommand : ICommand
{
private readonly Action<object?> execute;
private readonly Func<object?, bool> canExecute;
public RelayCommand(
Action<object?> execute,
Func<object?, bool>? canExecute = null)
{
this.execute = execute;
this.canExecute = canExecute ?? (_ => true);
}
public bool CanExecute(object? parameter) => this.canExecute(parameter);
public void Execute(object? parameter)
{
this.execute(parameter);
}
public event EventHandler? CanExecuteChanged;
}
// on your viewmodel add...
public ICommand RemoveFirstItemCommand { get; set; }
private void RemoveFirstItem(object? param)
{
if (this.Items.Count > 0)
{
this.Items.RemoveAt(0);
}
}
// ...and in the constructor init the command
this.RemoveFirstItemCommand = new RelayCommand(this.RemoveFirstItem);
I got a solution which achieved the goal, but I'm not sure if it's the right way.
There is a "Microsoft.Xaml.Behaviors" which provided "Interaction.Triggers" that contains "ComparisonCondition". I can use it to bind a value to determine the EventCommand is raised or not.
I updated the code as following:
ShellViewModel.cs
using Caliburn.Micro;
using System;
using System.Windows.Controls;
using WpfApp.Commands;
namespace WpfApp.ViewModels
{
public class ShellViewModel : Conductor<object>.Collection.OneActive
{
private bool _IsEnableSelectionChangedCommand = true;
public bool IsEnableSelectionChangedCommand
{
get => _IsEnableSelectionChangedCommand;
set
{
_IsEnableSelectionChangedCommand = value;
NotifyOfPropertyChange(() => IsEnableSelectionChangedCommand);
}
}
private BindableCollection<string> _myCollection = new BindableCollection<string>() { "item1", "item2"};
public BindableCollection<string> MyCollection
{
get => _myCollection;
set
{
_myCollection = value;
NotifyOfPropertyChange(() => MyCollection);
}
}
private string _selectMyListValue = "item1";
public DelegateCommand<object> DoSelectionChangedCommand { get; }
public ShellViewModel()
{
DoSelectionChangedCommand = new DelegateCommand<object>(comboBox1_SelectionChanged, CanExecute);
}
private bool CanExecute(object param)
{
return true;
}
private void comboBox1_SelectionChanged(object param)
{
SelectionChangedEventArgs e = param as SelectionChangedEventArgs;
ComboBox item = e.Source as ComboBox;
// Do something...
}
public string SelectMyListValue
{
get => _selectMyListValue;
set
{
_selectMyListValue = value;
NotifyOfPropertyChange(nameof(SelectMyListValue));
}
}
public void Button1_Click(object sender, EventArgs e)
{
IsEnableSelectionChangedCommand = false;
MyCollection.RemoveAt(0);
IsEnableSelectionChangedCommand = true;
}
}
}
ShellView.xaml
<UserControl x:Class="WpfApp.Views.ShellView"
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:cal="http://caliburnmicro.com"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
xmlns:cmd="clr-namespace:WpfApp.Commands"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height=" auto"/>
<RowDefinition Height=" auto"/>
</Grid.RowDefinitions>
<ComboBox Name="comboBox1" Grid.Row="0" ItemsSource="{Binding MyCollection}" SelectedValue="{Binding SelectMyListValue}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<cmd:EventCommand Command="{Binding DoSelectionChangedCommand}" />
<i:Interaction.Behaviors>
<i:ConditionBehavior>
<i:ConditionalExpression>
<i:ComparisonCondition LeftOperand= "{Binding IsEnableSelectionChangedCommand}" Operator="Equal" RightOperand="True"/>
</i:ConditionalExpression>
</i:ConditionBehavior>
</i:Interaction.Behaviors>
</i:EventTrigger>
</i:Interaction.Triggers>
</ComboBox>
<Button Name="Button1" Grid.Row="1" Content="Delete"
cal:Message.Attach="[Event Click]=[Action Button1_Click($source,$eventArgs)]" />
</Grid>
</UserControl>

Login Window in WPF Prism

I'm implementing a login window before my shell runs. How will I run the code and say that after authentication in the login window, proceed with the execution of shell application.
Here is my initial code:
LoginViewModel.cs
public event EventHandler LoginCompleted;
private void RaiseLoginCompletedEvent()
{
LoginCompleted?.Invoke(this, EventArgs.Empty);
}
Bootstraper.cs from the Shell
My problem here is that I cannot instantiate my LoginModel since the constructor of my Model has a parameter to use my Services Interface.
Is there any solution for this? Thanks!
New up an instance of a class that implements the ILoginAuth interface yourself:
var loginVM = new LoginViewModel(new LoginAuth());
...or let the container do it for you:
var loginVM = new LoginViewModel(Container.Resolve<ILoginAuth>());
For the latter option to work, you must register your type mappings by overriding the RegisterTypes method:
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.Register<ILoginAuth, LoginAuth>();
}
Another method of doing this:
ILoginAuth auth = CommonServiceLocator.ServiceLocator.Current.GetInstance<ILoginAuth>();
This way you don't have to include ILoginAuth in your constructor. Also, you can do this from any where!
<pre>
/*Brian code modified */
public interface ICloseWindow {
Action Close {
get;
set;
}
}
public partial class LoginWindow: Window {
public LoginWindow(ILoginViewModel viewModel) {
InitializeComponent();
DataContext = viewModel;
Loaded += MainWindow_Loaded;
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e) {
if (DataContext is ICloseWindow vm) {
vm.Close += () =>{
DialogResult = true;
};
}
}
private void Close_Window(object sender, RoutedEventArgs e) {
DialogResult = false;
}
}
/*App.xaml.cs*/
protected override void InitializeShell(Window shell) {
Window login = Container.Resolve < LoginWindow > ();
var result = login.ShowDialog();
if (!result.Value) {
Application.Current.Shutdown();
}
else {
base.InitializeShell(shell);
}
}
public class LoginViewModel: BindableBase,
ILoginViewModel,
ICloseWindow {
private string _userName;
private string _password;
private bool _isAuthenticated;
private ICommand _authenticateUserCommand;
private IEventAggregator _eventAggregator;
public Action Close {
get;
set;
}
public ICommand AuthenticateUserCommand {
get =>_authenticateUserCommand;
set =>_authenticateUserCommand = value;
}
public LoginViewModel(IEventAggregator eventAggregator) {
AuthenticateUserCommand = new DelegateCommand < object > (AuthenticateUser);
_eventAggregator = eventAggregator;
}
private void AuthenticateUser(object parameter) {
var passwordBox = parameter as PasswordBox;
var password = passwordBox.Password;
if (password == "password") {
_isAuthenticated = true;
_eventAggregator.GetEvent < MessageSentEvent > ().Publish("Login Data");
}
if (_isAuthenticated) {
Close ? .Invoke();
}
}
public string UserName {
get =>_userName;
set =>_userName = value;
}
public string Password {
get {
return _password;
}
set {
if (_password != value) {
_password = value;
RaisePropertyChanged(nameof(Password));
}
}
}
}
<Window x:Class="YourApplication.Views.LoginWindow"
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:local="clr-namespace:YourApplication"
mc:Ignorable="d"
Title="LoginWindow"
Height="450"
Width="800"
WindowStartupLocation="CenterScreen"
WindowStyle="None"
x:Name="WindowBorder"
RenderOptions.BitmapScalingMode="HighQuality">
<Grid SnapsToDevicePixels="True"
UseLayoutRounding="True"
TextOptions.TextFormattingMode="Display"
TextOptions.TextRenderingMode="ClearType">
<DockPanel>
<DockPanel DockPanel.Dock="Left"
Width="400"
LastChildFill="True">
<Canvas>
<Canvas.Background>
<ImageBrush ImageSource="pack://application:,,,/YourApplication;component/Images/Splash.png" />
</Canvas.Background>
<TextBlock Margin="4,0,0,4"
VerticalAlignment="Center"
Foreground="#FFAAAAAA"
TextWrapping="NoWrap"
Text="Library Management System"
FontSize="16"
Background="Transparent"
DockPanel.Dock="Top" />
</Canvas>
</DockPanel>
<DockPanel LastChildFill="True">
<Button x:Name="PART_CLOSE"
DockPanel.Dock="Top"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Margin="5"
Height="20"
Width="20"
Style="{DynamicResource MetroWindowButtonStyle}"
Click="Close_Window">
<Path Data="F1M54.0573,47.8776L38.1771,31.9974 54.0547,16.1198C55.7604,14.4141 55.7604,11.6511 54.0573,9.94531 52.3516,8.23962 49.5859,8.23962 47.8802,9.94531L32.0026,25.8229 16.1224,9.94531C14.4167,8.23962 11.6511,8.23962 9.94794,9.94531 8.24219,11.6511 8.24219,14.4141 9.94794,16.1198L25.8255,32 9.94794,47.8776C8.24219,49.5834 8.24219,52.3477 9.94794,54.0534 11.6511,55.7572 14.4167,55.7585 16.1224,54.0534L32.0026,38.1745 47.8802,54.0534C49.5859,55.7585 52.3516,55.7572 54.0573,54.0534 55.7604,52.3477 55.763,49.5834 54.0573,47.8776z"
Stretch="Uniform"
Fill="#FFAAAAAA"
Width="10"
Margin="0,0,0,0"></Path>
</Button>
<StackPanel>
<PasswordBox x:Name="txtPassword"
Margin="2,20,10,10"
Height="22"
Width="100" />
<Button Width="100"
Height="22"
Margin="10,150,10,10"
Content="Login"
Command="{Binding AuthenticateUserCommand}"
CommandParameter="{Binding ElementName=txtPassword}" />
</StackPanel>
</DockPanel>
</DockPanel>
</Grid>
</Window>
</pre>

Why is my busy page not working?

I'm trying to develop a busy Window as said here and here. I want a grid to be visible whenver I need it to be visible, for example while I'm doing a long task.
I did this til now:
The XAML:
<Window x:Class="LoadingWindow2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:loadingWindow2="clr-namespace:LoadingWindow2"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<loadingWindow2:BoolToVisibilityConverter x:Key="boolConverter"/>
</Window.Resources>
<Grid>
<Label HorizontalAlignment="Right">
<Hyperlink Command="{Binding Path=DoSomething}">Do Something</Hyperlink>
</Label>
<Border BorderBrush="Black" BorderThickness="1" Background="#80000000" Visibility="{Binding IsBusy, Converter={StaticResource boolConverter}}" Grid.RowSpan="3">
<Grid>
<TextBlock Margin="0" TextWrapping="Wrap" Text="Please Wait..." HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="24" FontWeight="Bold" Foreground="#7EFFFFFF"/>
</Grid>
</Border>
</Grid>
My .cs:
The BusyViewModel.cs:
public class BusyViewModel : INotifyPropertyChanged
{
private ICommand doSomethingCommand;
public event PropertyChangedEventHandler PropertyChanged;
public bool IsBusy { get; set; }
public ICommand DoSomething
{
get { return doSomethingCommand ?? (doSomethingCommand = new DelegateCommand(LongRunningTask)); }
}
private void LongRunningTask()
{
var task = new Task(ComputeResults);
task.Start();
}
private void ComputeResults()
{
this.IsBusy = true;
Thread.Sleep(5000);
this.IsBusy = false;
}
}
The DelegateCommand.cs:
public class DelegateCommand : ICommand
{
private readonly Action executeMethod;
private readonly Func<bool> canExecuteMethod;
public DelegateCommand(Action executeMethod)
: this(executeMethod, () => true)
{
}
public DelegateCommand(Action executeMethod, Func<bool> canExecuteMethod)
{
if (executeMethod == null)
throw new ArgumentNullException("executeMethod");
if (canExecuteMethod == null)
throw new ArgumentNullException("canExecuteMethod");
this.executeMethod = executeMethod;
this.canExecuteMethod = canExecuteMethod;
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public bool CanExecute(object stupid)
{
return CanExecute();
}
public bool CanExecute()
{
return canExecuteMethod();
}
public void Execute(object parameter)
{
Execute();
}
public void Execute()
{
executeMethod();
}
public void OnCanExecuteChanged()
{
CommandManager.InvalidateRequerySuggested();
}
}
MainWindow.xaml.cs:
public MainWindow()
{
InitializeComponent();
this.DataContext = new BusyViewModel();
}
I downloaded the source code from the first link I copied, and the busy Grid is showing. But in my case... is NOT!!! What I'm doing wrong here?
EDIT: I deleted the Converter as suggested. But it's not working yet... I add my `MainWindow.xaml.cs"
The whole source: here
There is a converter available from WPF already, the "booleanToVisibilityConverter" that does the job.
See http://msdn.microsoft.com/de-de/library/system.windows.controls.booleantovisibilityconverter%28v=vs.110%29.aspx
Edit your xaml like this:
<Window x:Class="LoadingWindow2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:loadingWindow2="clr-namespace:LoadingWindow2"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<BooleanToVisibilityConverter x:Key="boolConverter"/>
</Window.Resources>
<Grid x:Name="ROOT">
<Label HorizontalAlignment="Right">
<Hyperlink Command="{Binding Path=DoSomething}">Do Something</Hyperlink>
</Label>
<Border BorderBrush="Black" BorderThickness="1" Background="#80000000" Visibility="{Binding Path=IsBusy, Converter={StaticResource boolConverter}}" Grid.RowSpan="3">
<Grid>
<TextBlock Margin="0" TextWrapping="Wrap" Text="Please Wait..."
horizontalAlignment="Center" VerticalAlignment="Center" FontSize="24" FontWeight="Bold" Foreground="#7EFFFFFF"/>
</Border>
</Grid>
EDIT: Implementation of BusyViewMOdel
public class BusyViewModel : INotifyPropertyChanged
{
private ICommand doSomethingCommand;
public event PropertyChangedEventHandler PropertyChanged;
private bool _isBusy = false;
public bool IsBusy
{
get { return _isBusy; }
set
{
_isBusy = value;
OnPropertyChanged("IsBusy");
}
}
// Create the OnPropertyChanged method to raise the event
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
public ICommand DoSomething
{
get { return doSomethingCommand ?? (doSomethingCommand = new DelegateCommand(LongRunningTask)); }
}
private void LongRunningTask()
{
var task = new Task(ComputeResults);
task.Start();
}
private void ComputeResults()
{
this.IsBusy = true;
Thread.Sleep(5000);
this.IsBusy = false;
}
}
See http://msdn.microsoft.com/de-de/library/ms743695%28v=vs.110%29.aspx
EDIT: Try to set the data context on the root grid by giving the grid a name and instead of this.DataContext = ... in public MainWindow() ...do ROOT.DataContext = .... See updated xaml!
EDIT: Got it working. See this code of class BusyViewModel.
private void LongRunningTask()
{
var task = new Task(ComputeResults);
task.Start();
}
private void ComputeResults()
{
this.IsBusy = true; // you did _isBusy = true. but to invoke OnPropertyChanged you need to use the setter, thus IsBusy! Works now even if set in the worker thread. Put it back to ComputeResults!
Thread.Sleep(5000);
this.IsBusy = false;
}

set color in class property and use that property for binding in XAML

I want to set a color in a property and use that property to bind to the background color of my window.
i.e the value set in the property will be binded to my window background.
The code below is not working for me.
class
public static class configclas
{
public static int UserId { get; set; }
public static string UserName { get; set; }
private static string _klant;
public static String Klant
{
get { return _klant; }
set { _klant = value; }
}
}
XAML
<Window x:Class="SmartAccount.Test"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wpfTool="clr-namespace:Xceed.Wpf.Toolkit;assembly=Xceed.Wpf.Toolkit"
xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero"
Title="Test" Height="300" Width="300">
<Grid x:Name="setcolor" Background="{Binding Klant}">
<wpfTool:ColorPicker x:Name="colorPicker" Width="40" Height="30" Canvas.Left="3" Visibility="Visible" Canvas.Top="208"></wpfTool:ColorPicker>
<Button x:Name="btnsubmit" Height="30" Width="50" Content="submit" Margin="0,90,0,0" Click="btnsubmit_Click_1"></Button>
</Grid>
</Window>
test.xaml.cs
private void btnsubmit_Click_1(object sender, RoutedEventArgs e)
{
var clrr = colorPicker.SelectedColor.ToString();
BrushConverter bc = new BrushConverter();
var bgcolor = (System.Windows.Media.Brush)bc.ConvertFrom(colorPicker.SelectedColor.ToString());
configclas.Klant = clrr;
}
}

INotifyPropertyChanged.PropertyChanged always NULL

I know I am doing something wrong here but what. Please have a look and point out my error.
I will see "Peter" in my textbox but no "Jack" after the button click.
My class
namespace App
{
class Person : INotifyPropertyChanged
{
private string name;
public String Name
{
get { return name; }
set { name = value; OnPropertyChanged("Name"); }
}
public Person()
{
Name = "Peter";
}
public void SetName(string newname)
{
Name = newname;
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string prop)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(prop));
}
}
}
}
My XAML
<Window x:Class="test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:app="clr-namespace:App"
Title="MainWindow" Height="400" Width="400">
<Grid>
<Grid.Resources>
<app:Person x:Key="person"/>
</Grid.Resources>
<TextBox Width="100" Height="26" Text="{Binding Source={StaticResource person}, Path=Name, Mode=TwoWay}" />
<Button Content="Button" Height="23" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click" />
</Grid>
And my codebehind
public partial class MainWindow : Window
{
Person person;
public MainWindow()
{
InitializeComponent();
person = new Person();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
person.SetName("Jack");
}
}
Thanks.
You have two instances of Person. PropertyChanged is not null in the static resource
This isn't really what StaticResources are for. Get rid of the static resource, change the binding to:
{Binding Path=Name, Mode=TwoWay}
and add this to your constructor:
DataContext = person;
That object person in codebehind of MainWindow is not the same object you have binding to in XAML
If you want to use that object from resources you have to find it in code behind so something like this in constructor
person = (Person)Resources["person"];

Resources