I have a borderless transparent wpf window (WindowStyle=None) that I would like to be able to resize from all sides. Currently resizing is only working with the above settings if I set ResizeMode=CanResizeWithGrip. This is nice for the visual cue, but not so nice because you can only resize from one corner.
I would like to do this with an adorner, so I can also give a visual cue when the window is in resize mode (which can be switched on and off). Is this possible? If so, how would I go about this?
This question has already been answered somewhere on stackoverflow. I can't really find it now, but here is how I did it.
MainWindow:
<Window x:Class="Solution.Views.Main.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" MinWidth="1000" MinHeight="500" WindowStyle="None" AllowsTransparency="False" BorderThickness="0" ResizeMode="NoResize">
<Window.TaskbarItemInfo>
<TaskbarItemInfo />
</Window.TaskbarItemInfo>
<Grid>
<Border MouseLeftButtonDown="WindowResizeEast" MouseEnter="BorderVertical_OnMouseEnter" MouseLeave="BorderAll_OnMouseLeave" VerticalAlignment="Stretch" HorizontalAlignment="Right" Width="1" Background="Black"/>
<Border MouseLeftButtonDown="WindowResizeWest" MouseEnter="BorderVertical_OnMouseEnter" MouseLeave="BorderAll_OnMouseLeave" VerticalAlignment="Stretch" HorizontalAlignment="Left" Width="1" Background="Black"/>
<Border MouseLeftButtonDown="WindowResizeNorth" MouseEnter="BorderHorizontal_OnMouseEnter" MouseLeave="BorderAll_OnMouseLeave" VerticalAlignment="Top" HorizontalAlignment="Stretch" Height="1" Background="Black"/>
<Border MouseLeftButtonDown="WindowResizeSouth" MouseEnter="BorderHorizontal_OnMouseEnter" MouseLeave="BorderAll_OnMouseLeave" VerticalAlignment="Bottom" HorizontalAlignment="Stretch" Height="1" Background="Black"/>
<Border VerticalAlignment="Bottom" HorizontalAlignment="Right" Width="20" Height="20" MouseEnter="BorderSouthEast_OnMouseEnter" MouseLeave="BorderAll_OnMouseLeave" MouseLeftButtonDown="UIElement_OnMouseLeftButtonDown">
<Grid>
<Path Stroke="Gray" StrokeThickness="1" Data=" M 5 20 L 20 5 M 10 20 L 20 10 M 15 20 L 20 15"/>
</Grid>
</Border>
</Grid>
</Window>
MainWindow Code:
using System;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using PrmWpf.Services;
public partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
}
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern IntPtr SendMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
[DllImportAttribute("user32.dll")]
public static extern bool ReleaseCapture();
private void WindowResizeNorth(object sender, MouseButtonEventArgs e) //PreviewMousLeftButtonDown
{
var hwndSource = PresentationSource.FromVisual((Visual)sender) as HwndSource;
SendMessage(hwndSource.Handle, 0x112, (IntPtr)ResizeDirection.Top, IntPtr.Zero);
}
private void WindowResizeSouth(object sender, MouseButtonEventArgs e) //PreviewMousLeftButtonDown
{
var hwndSource = PresentationSource.FromVisual((Visual)sender) as HwndSource;
SendMessage(hwndSource.Handle, 0x112, (IntPtr)ResizeDirection.Bottom, IntPtr.Zero);
}
private void WindowResizeWest(object sender, MouseButtonEventArgs e) //PreviewMousLeftButtonDown
{
var hwndSource = PresentationSource.FromVisual((Visual)sender) as HwndSource;
SendMessage(hwndSource.Handle, 0x112, (IntPtr)ResizeDirection.Left, IntPtr.Zero);
}
private void WindowResizeEast(object sender, MouseButtonEventArgs e) //PreviewMousLeftButtonDown
{
var hwndSource = PresentationSource.FromVisual((Visual)sender) as HwndSource;
SendMessage(hwndSource.Handle, 0x112, (IntPtr)ResizeDirection.Right, IntPtr.Zero);
}
private enum ResizeDirection { Left = 61441, Right = 61442, Top = 61443, Bottom = 61446, BottomRight = 61448, }
private void BorderVertical_OnMouseEnter(object sender, MouseEventArgs e)
{
Mouse.OverrideCursor = Cursors.SizeWE;
}
private void BorderHorizontal_OnMouseEnter(object sender, MouseEventArgs e)
{
Mouse.OverrideCursor = Cursors.SizeNS;
}
private void BorderAll_OnMouseLeave(object sender, MouseEventArgs e)
{
Mouse.OverrideCursor = Cursors.Arrow;
}
private void BorderSouthEast_OnMouseEnter(object sender, MouseEventArgs e)
{
Mouse.OverrideCursor = Cursors.SizeNWSE;
}
private void UIElement_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var hwndSource = PresentationSource.FromVisual((Visual)sender) as HwndSource;
SendMessage(hwndSource.Handle, 0x112, (IntPtr)ResizeDirection.BottomRight, IntPtr.Zero);
}
}
Related
Created a simple checkbox in WPF.
The single click toggles the checkbox status in the UI.
I want the checkbox status to be changed when I double click on checkbox text. Please help me with code below.
The only control in the xaml:
<Grid>
<CheckBox Content="CheckBox" HorizontalAlignment="Left" Height="60" Margin="144,93,0,0" VerticalAlignment="Top" Width="392"/>
</Grid>
I could not find a solution with standart CheckBox Control. I've created my own checkBox via UserControl.
DoubleClickCheckBox.xaml (UserControl)
<Grid VerticalAlignment="Center" HorizontalAlignment="Center" Loaded="Grid_Loaded">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<CheckBox Name="checkBox" Checked="CheckBox_Checked" Unchecked="CheckBox_Unchecked"/>
<TextBlock Name="textBlock" MouseDown="TextBlock_MouseDown" TextAlignment="Center" Grid.Column="1" Margin="4,0,4,0"/>
</Grid>
DoubleClickCheckBox.xaml.cs (UserControl)
public partial class DoubleClickCheckBox : UserControl
{
public string Text { get; set; }
public bool IsChecked { get; set; }
public event EventHandler UserControlChecked;
public event EventHandler UserControlUnChecked;
public DoubleClickCheckBox()
{
InitializeComponent();
}
private void Grid_Loaded(object sender, RoutedEventArgs e)
{
this.checkBox.IsChecked = this.IsChecked;
this.textBlock.Text = this.Text;
}
private void TextBlock_MouseDown(object sender, MouseButtonEventArgs e)
{
if(e.ClickCount == 2)
this.checkBox.IsChecked = !this.checkBox.IsChecked;
}
private void CheckBox_Checked(object sender, RoutedEventArgs e)
{
if (UserControlChecked != null)
UserControlChecked(this, EventArgs.Empty);
}
private void CheckBox_Unchecked(object sender, RoutedEventArgs e)
{
if (UserControlUnChecked != null)
UserControlUnChecked(this, EventArgs.Empty);
}
}
MainWindow.xaml
<Grid>
<local:DoubleClickCheckBox VerticalAlignment="Center" HorizontalAlignment="Center" Background="Aqua" Text="Test" IsChecked="False" UserControlChecked="DoubleClickCheckBox_UserControlChecked" UserControlUnChecked="DoubleClickCheckBox_UserControlUnChecked"/>
</Grid>
MainWindow.xaml.cs
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void DoubleClickCheckBox_UserControlChecked(object sender, EventArgs e)
{
this.Title = "Checked";
}
private void DoubleClickCheckBox_UserControlUnChecked(object sender, EventArgs e)
{
this.Title = "UnChecked";
}
}
You can customize everything with this style. I customized only checked and unchecked events. It is up to you in future.
EDIT: As post owner wanted, i enabled single click again.
Removed CheckBox_PreviewMouseButtonDown event.
If you just want to toggle the checkbox status when double clicked, then simply make an CheckBox_MouseDoubleClick Event and set the IsChecked property to true. But take care, this Solution is not within the MVVM pattern.
This is a really strange problem, I have a listview that I want to drop files onto, I know how to get the file info etc, and bizarrely I actually had it working fine, but then it seemed to just stop.
I have tried creating a new project with just a listview object, allowdrop=true, dragenter/drop events created, dragenter contains e.handled=true and e.effects = effects.none.
but the events just don't fire, I have a project that was created on an earlier version of VS, and this works fine !!
here is the xmal
<Window x:Name="mainWin" x:Class="droptest.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">
<Window.Resources>
<Style x:Key="ColumnHeaders" TargetType="{x:Type GridViewColumnHeader}">
<Setter Property="Visibility" Value="Collapsed"/>
</Style>
</Window.Resources>
<Grid>
<ListView x:Name="ImageList" AllowDrop="True" HorizontalAlignment="Left" Height="204" Margin="65,69,0,0" VerticalAlignment="Top" Width="374" DragEnter="ImageList_DragEnter" Drop="ImageList_Drop" DragOver="ImageList_DragOver" DragLeave="ImageList_DragLeave">
<ListView.View>
<GridView ColumnHeaderContainerStyle="{StaticResource ColumnHeaders}">
<GridViewColumn/>
</GridView>
</ListView.View>
</ListView>
</Grid>
</Window>
and here is the code
namespace droptest
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void ImageList_DragEnter(object sender, DragEventArgs e)
{
e.Handled = true;
e.Effects = DragDropEffects.None;
}
private void ImageList_Drop(object sender, DragEventArgs e)
{
}
private void ImageList_PreviewDragOver(object sender, DragEventArgs e)
{
e.Handled = true;
e.Effects = DragDropEffects.None;
}
private void ImageList_PreviewDrop(object sender, DragEventArgs e)
{
}
private void ImageList_DragOver(object sender, DragEventArgs e)
{
e.Handled = true;
e.Effects = DragDropEffects.None;
}
private void ImageList_DragLeave(object sender, DragEventArgs e)
{
e.Handled = true;
e.Effects = DragDropEffects.None;
}
}
}
I don't think I am doing anything wrong, in fact I am sure I aren't, as I had it working..
any pointers would be much appreciated.
Why doesn't my input gesture work in the following?
public class CustomRoutedUICommand : RoutedUICommand
{
private static RoutedUICommand _doSomethingCommand = null;
static CustomRoutedUICommand()
{
InputGestureCollection myInputs = new InputGestureCollection();
myInputs.Add(new KeyGesture(Key.G, ModifierKeys.Control | ModifierKeys.Shift));
_doSomethingCommand = new RoutedUICommand("DoSomething", "DoSomething", typeof(CustomRoutedUICommand), myInputs);
}
public static RoutedUICommand DoSomethingCommand { get { return _doSomethingCommand; } }
}
<Button Height="23" HorizontalAlignment="Left"
Command="{x:Static Control:CustomRoutedUICommand.DoSomethingCommand}"
CommandManager.CanExecute="Command_CanExecute" CommandManager.Executed="Command_Executed"
Content="{Binding RelativeSource={RelativeSource Mode=Self}, Path=Command.Text}"
Margin="12,54,0,0" Name="Command" VerticalAlignment="Top" Width="Auto" Padding="2"/>
private void Command_Executed(object sender, ExecutedRoutedEventArgs e)
{
MessageBox.Show("Hii");
}
In this case, the Command to work, need to have been an element logical focus, otherwise it will not work. You can specify KeyGesture a XAML way:
<Button Height="23" Content="Test" Name="Command" VerticalAlignment="Top"
Command="{x:Static Control:CustomRoutedUICommand.DoSomethingCommand}"
CommandManager.Executed="Command_Executed"
CommandManager.CanExecute="Command_CanExecute">
<Button.InputBindings>
<KeyBinding Command="{x:Static Control:CustomRoutedUICommand.DoSomethingCommand}" Gesture="CTRL+G" />
</Button.InputBindings>
</Button>
It works when the focus will be, it can be specified as follows:
Command.Focus();
To make your case to work, you need to use CommandBindings like this:
XAML
<Window x:Class="InputGestureHelp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Control="clr-namespace:InputGestureHelp"
WindowStartupLocation="CenterScreen"
ContentRendered="Window_ContentRendered"
Title="MainWindow" Height="350" Width="525">
<Window.CommandBindings>
<CommandBinding Command="{x:Static Control:CustomRoutedUICommand.DoSomethingCommand}"
Executed="Command_Executed" CanExecute="Command_CanExecute" />
</Window.CommandBindings>
<Grid>
<Button Height="23" Content="Test" Name="TestButton"
VerticalAlignment="Top"
Command="{x:Static Control:CustomRoutedUICommand.DoSomethingCommand}" />
</Grid>
</Window>
Code behind
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Command_Executed(object sender, ExecutedRoutedEventArgs e)
{
MessageBox.Show("Hii");
}
private void Command_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
}
private void Window_ContentRendered(object sender, EventArgs e)
{
TestButton.Focus();
}
}
public class CustomRoutedUICommand : RoutedUICommand
{
private static RoutedUICommand _doSomethingCommand;
static CustomRoutedUICommand()
{
InputGestureCollection myInputs = new InputGestureCollection();
myInputs.Add(new KeyGesture(Key.G, ModifierKeys.Control, "Ctrl + G"));
_doSomethingCommand = new RoutedUICommand("DoSomething", "DoSomething", typeof(CustomRoutedUICommand), myInputs);
}
public static RoutedUICommand DoSomethingCommand
{
get
{
return _doSomethingCommand;
}
}
}
I have ListBox. when i click on ListBox item I have to show item information in popup But it does not close after clicking out side. I am creating popup in itemsselected event. how to handle popup close?
One approach is to create a canvas with a transparent background that you make visible at the same time as opening the Popup and attaching to is Mouse down event to closed the popup. Like this:-
Xaml:-
<Grid x:Name="LayoutRoot" Background="White" >
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Popup x:Name="MyPopup" Closed="MyPopup_Closed" HorizontalOffset="100" VerticalOffset="100" Opened="Popup_Opened">
<ListBox x:Name="PopupChild" MaxHeight="300" LostFocus="PopupChild_LostFocus">
<sys:String>Hello World</sys:String>
</ListBox>
</Popup>
<Button Content="Open Popup" Grid.Row="1" Click="Button_Click" />
<Canvas x:Name="PopupOpen" Visibility="Collapsed" Background="Transparent" Grid.RowSpan="2" MouseLeftButtonDown="PopupOpen_MouseLeftButtonDown" />
</Grid>
Code:-
private void Button_Click(object sender, RoutedEventArgs e)
{
MyPopup.IsOpen = true;
}
private void Popup_Opened(object sender, EventArgs e)
{
PopupOpen.Visibility = Visibility.Visible;
}
private void PopupChild_LostFocus(object sender, RoutedEventArgs e)
{
MyPopup.IsOpen = false;
}
private void PopupOpen_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
MyPopup.IsOpen = false;
}
private void MyPopup_Closed(object sender, EventArgs e)
{
PopupOpen.Visibility = Visibility.Collapsed;
}
Note that its important that if your popup contains a control that can receive the focus that you also handle LostFocus.
This is similar to a question that I had. Take a look at How to dismiss a popup in Silverlight when clicking outside of the control?. I posted in my solution an extension method that's been very helpful in making popups close when clicking outside of them.
I'm not quite sure what you mean by "clicking out side" because popups act in a modal way.
You should set up your popup window as a ChildWindow. Then you can handle the Closed event.
Here's a very simple sample that shows a selected string from a listbox in a main window.
First the main window:
<UserControl x:Class="PopupTest.MainPage"
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"
d:DesignHeight="300" d:DesignWidth="400">
<Grid x:Name="LayoutRoot" Background="White">
<StackPanel Orientation="Vertical">
<ListBox x:Name="SomeList" Width="100" Height="100" />
<TextBlock x:Name="DialogResult" Width="100" />
</StackPanel>
</Grid>
In the codebehind, the popup is triggered when the list selection changes. Simply set up a Closed handler. In this example, I simply put the chosen list item into a textblock, then upon closing the popup, I just put the dialog result in a textblock on the main window (to show if the user pushed ok or cancel).
public MainPage()
{
InitializeComponent();
SomeList.SelectionChanged += new SelectionChangedEventHandler(SomeList_SelectionChanged);
SomeList.Items.Add("one");
SomeList.Items.Add("two");
SomeList.Items.Add("three");
}
void SomeList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var popup = new SomePopup();
popup.Closed += new EventHandler(popup_Closed);
popup.ChosenItem.Text = (string)SomeList.SelectedItem;
DialogResult.Text = "";
popup.Show();
}
void popup_Closed(object sender, EventArgs e)
{
var popup = sender as SomePopup;
if (popup.DialogResult == true)
DialogResult.Text = "Ok";
else
DialogResult.Text = "Cancel";
}
The popup closes when the user pushes Ok or Cancel, because the DialogResult value is set in the popup's code-behind:
private void OKButton_Click(object sender, RoutedEventArgs e)
{
this.DialogResult = true;
}
private void CancelButton_Click(object sender, RoutedEventArgs e)
{
this.DialogResult = false;
}
Yes, I know it sounds weird, but it doesn't, the question is why, and if there's a work around. It works with everything, even when you hit PrintScreen or Pause keys, CanExecute fires. So after doing a drag drop, in order to make it fire, you have to do "something" else, like a mouse click, focus, hit a key, anything. That'll make the event fire, and allow Execute to happen. Anyway, here's my code, I know it's long, but it'll help you help me.
I found this bug in our large main project, so I simplified it to this little app to isolate the problem.
XAML:
<Window x:Class="DragNDropCommands.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="485" SizeToContent="Width" Loaded="Window_Loaded">
<Window.CommandBindings>
<CommandBinding Command="ApplicationCommands.New" CanExecute="NewCanExecute" Executed="NewExecuted" />
<CommandBinding Command="ApplicationCommands.Save" CanExecute="SaveCanExecute" Executed="SaveExecuted" />
<CommandBinding Command="ApplicationCommands.Undo" CanExecute="UndoCanExecute" Executed="UndoExecuted" />
<CommandBinding Command="ApplicationCommands.Redo" CanExecute="RedoCanExecute" Executed="RedoExecuted" />
</Window.CommandBindings>
<Grid Margin="8">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Button Command="ApplicationCommands.New" Grid.Row="0" Grid.Column="0" FontWeight="Bold" Content="New" Width="80" Margin="8"></Button>
<Button Command="ApplicationCommands.Save" Grid.Row="0" Grid.Column="1" FontWeight="Bold" Content="Save" Width="80" Margin="8"></Button>
<Button Command="ApplicationCommands.Undo" Grid.Row="0" Grid.Column="2" FontWeight="Bold" Content="Undo" Width="80" Margin="8"></Button>
<Button Command="ApplicationCommands.Redo" Grid.Row="0" Grid.Column="3" FontWeight="Bold" Content="Redo" Width="80" Margin="8"></Button>
<CheckBox Grid.Row="1" Grid.Column="0" Margin="8" IsChecked="{Binding Path=AllowNew, Mode=TwoWay}">Allow New</CheckBox>
<CheckBox Grid.Row="1" Grid.Column="1" Margin="8" IsChecked="{Binding Path=AllowSave}">Allow Save</CheckBox>
<CheckBox Grid.Row="1" Grid.Column="2" Margin="8" IsChecked="{Binding Path=AllowUndo}">Allow Undo</CheckBox>
<CheckBox Grid.Row="1" Grid.Column="3" Margin="8" IsChecked="{Binding Path=AllowRedo}">Allow Redo</CheckBox>
<Label x:Name="labelDrag" Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="2" BorderBrush="Black" BorderThickness="1" MouseDown="Label_MouseDown"
Background="LightBlue" HorizontalContentAlignment="Center" Margin="8">Drag this label...</Label>
<Label x:Name="labelDropNew" Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" BorderBrush="Black" BorderThickness="1" Drop="labelDropNew_Drop"
Background="LightGray" HorizontalContentAlignment="Center" Margin="8" AllowDrop="True">...here to toggle AllowNew</Label>
<Label x:Name="labelDropSave" Grid.Row="3" Grid.Column="2" Grid.ColumnSpan="2" BorderBrush="Black" BorderThickness="1" Drop="labelDropSave_Drop"
Background="LightGray" HorizontalContentAlignment="Center" Margin="8" AllowDrop="True">...here to toggle AllowSave</Label>
<ListBox x:Name="listViewLog" Grid.Row="4" Grid.ColumnSpan="4" Margin="8" Width="500">
</ListBox>
<Button Grid.Row="5" Grid.Column="1" Grid.ColumnSpan="2" Margin="8" Click="Button_Click">Clear list</Button>
</Grid>
</Window>
C#:
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace DragNDropCommands
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
private CommandControl commandControl = new CommandControl();
private int canExecuteCount = 1;
public Window1()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
this.DataContext = commandControl;
}
private void NewCanExecute(object sender, CanExecuteRoutedEventArgs e)
{
if (this.commandControl == null || listViewLog == null)
return;
e.CanExecute = this.commandControl.AllowNew;
listViewLog.Items.Add
(
String.Format
(
"{0} - NewCanExecute: {1} - commandControl.AllowNew: {2}",
canExecuteCount++, e.CanExecute, commandControl.AllowNew
)
);
}
private void NewExecuted(object sender, ExecutedRoutedEventArgs e)
{
MessageBox.Show("New executed");
}
private void SaveCanExecute(object sender, CanExecuteRoutedEventArgs e)
{
if (this.commandControl == null || listViewLog == null)
return;
e.CanExecute = this.commandControl.AllowSave;
listViewLog.Items.Add
(
String.Format
(
"{0} - SaveCanExecute: {1} - commandControl.AllowSave: {2}",
canExecuteCount++, e.CanExecute, commandControl.AllowSave
)
);
}
private void SaveExecuted(object sender, ExecutedRoutedEventArgs e)
{
MessageBox.Show("Save executed");
}
private void UndoCanExecute(object sender, CanExecuteRoutedEventArgs e)
{
if (this.commandControl == null || listViewLog == null)
return;
e.CanExecute = this.commandControl.AllowUndo;
listViewLog.Items.Add
(
String.Format
(
"{0} - UndoCanExecute: {1} - commandControl.AllowUndo: {2}",
canExecuteCount++, e.CanExecute, commandControl.AllowUndo
)
);
}
private void UndoExecuted(object sender, ExecutedRoutedEventArgs e)
{
MessageBox.Show("Undo executed");
}
private void RedoCanExecute(object sender, CanExecuteRoutedEventArgs e)
{
if (this.commandControl == null || listViewLog == null)
return;
e.CanExecute = this.commandControl.AllowRedo;
listViewLog.Items.Add
(
String.Format
(
"{0} - RedoCanExecute: {1} - commandControl.AllowRedo: {2}",
canExecuteCount++, e.CanExecute, commandControl.AllowRedo
)
);
}
private void RedoExecuted(object sender, ExecutedRoutedEventArgs e)
{
MessageBox.Show("Redo executed");
}
private void Button_Click(object sender, RoutedEventArgs e)
{
listViewLog.Items.Clear();
}
private void Label_MouseDown(object sender, MouseButtonEventArgs e)
{
Label label = (Label)sender;
if(e.LeftButton == MouseButtonState.Pressed)
DragDrop.DoDragDrop(label, label, DragDropEffects.Move);
}
private void labelDropNew_Drop(object sender, DragEventArgs e)
{
this.commandControl.AllowNew = !this.commandControl.AllowNew;
}
private void labelDropSave_Drop(object sender, DragEventArgs e)
{
this.commandControl.AllowSave = !this.commandControl.AllowSave;
}
}
public class CommandControl : DependencyObject
{
public bool AllowNew
{
get { return (bool)GetValue(AllowNewProperty); }
set { SetValue(AllowNewProperty, value); }
}
// Using a DependencyProperty as the backing store for AllowNew. This enables animation, styling, binding, etc...
public static readonly DependencyProperty AllowNewProperty =
DependencyProperty.Register("AllowNew", typeof(bool), typeof(CommandControl), new UIPropertyMetadata(false));
public bool AllowSave
{
get { return (bool)GetValue(AllowSaveProperty); }
set { SetValue(AllowSaveProperty, value); }
}
// Using a DependencyProperty as the backing store for AllowSave. This enables animation, styling, binding, etc...
public static readonly DependencyProperty AllowSaveProperty =
DependencyProperty.Register("AllowSave", typeof(bool), typeof(CommandControl), new UIPropertyMetadata(false));
public bool AllowUndo
{
get { return (bool)GetValue(AllowUndoProperty); }
set { SetValue(AllowUndoProperty, value); }
}
// Using a DependencyProperty as the backing store for AllowUndo. This enables animation, styling, binding, etc...
public static readonly DependencyProperty AllowUndoProperty =
DependencyProperty.Register("AllowUndo", typeof(bool), typeof(CommandControl), new UIPropertyMetadata(false));
public bool AllowRedo
{
get { return (bool)GetValue(AllowRedoProperty); }
set { SetValue(AllowRedoProperty, value); }
}
// Using a DependencyProperty as the backing store for AllowRedo. This enables animation, styling, binding, etc...
public static readonly DependencyProperty AllowRedoProperty =
DependencyProperty.Register("AllowRedo", typeof(bool), typeof(CommandControl), new UIPropertyMetadata(false));
}
}
You should be able to just copy paste and do a few name changes (files, namespaces) to get it running. I'd really love your help since this has been driving me nuts, and now that I finally discover the reason for the bug, I don't know what to do about it.
Any suggestion is really apreciatted.
Thanks in advance.
Just a quick suggestion:
You could use CommandManager.InvalidateRequerySuggested() in the drag and drop event handler to force the reexecution of CanExecute(). (Link)