Dialog should come to front on button click - wpf

I am using Prism 5. To show dialog, I am using InteractionRequest. IsModel Property is set to False, so when I click on the main window (from where Dialogs is raised), Dialogs went in background. Now what I am trying to implement is that when I click button again, dialog should come to front again.
Here is my custom PopupWindowActionclass:
public class CustomDialogWindow : PopupWindowAction
{
private Window window;
protected override Window GetWindow(INotification notification) {
window = base.GetWindow(notification);
return window;
}
public static readonly DependencyProperty SetFocusProperty =
DependencyProperty.Register("SetFocus", typeof(bool),
typeof(CustomDialogWindow), null);
public bool SetFocus {
get { return (bool)GetValue(SetFocusProperty); }
set {
if (value) {
if (window != null) {
window.Activate();
window.Focus();
}
}
SetValue(SetFocusProperty, value);
}
}
}
Here is my XMAL side configuration:
<prism:InteractionRequestTrigger SourceObject="{Binding ContainerMoveSummaryRequest, Mode=OneWay}">
<popout:CustomDialogWindow x:Name="ContentSummaryGridAction"
IsModal="False" SetFocus="{Binding SetFocusOnContainerMoveSummary,Mode=TwoWay}">
<popout:CustomDialogWindow.WindowContent>
<dialogs:ContainerMoveSummaryDialog />
</popout:CustomDialogWindow.WindowContent>
</popout:CustomDialogWindow>
</prism:InteractionRequestTrigger>
The problem is even though binding is two way, On changing SetFocusOnContainerMoveSummary , SetFocus is not getting change.
Please let me know any solution for this.

The problem is even though binding is two way, on changing SetFocusOnContainerMoveSummary, SetFocus is not getting called
This is expected behavior, the the framework circumvents the helper property and uses the dependency property directly.
You need to set a callback on the dependency property and go from there:
public static readonly DependencyProperty SetFocusProperty =
DependencyProperty.Register(nameof(SetFocus),
typeof(bool),
typeof(CustomDialogWindow),
new PropertyMetaData( default(bool), OnSetFocusChanged);
private static void OnSetFocusChanged( DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs )
{
// get the window from dependencyObject (= the CustomDialogWindow instance) and call SetFocus
}

Related

How to add a command to a xamdatagrid cellactivated event without breaking MVVM

i am using a XamDataGrid to display my data. Now I want to add different commands to each column.
Using the CellActivated event on the whole grid and then binding to ActiveCell wont work since the Viewmodel would have to know about the View and how to evaluate the Column from the object returned by ActiveCell.
I am looking for a way how to tell the XamDataGrid which command should be called.
I imagine something like this:
<igDP:Field Name="Dev" >
<igDP:Field.Settings>
<igDP:FieldSettings CellValuePresenterStyle="{StaticResource DevStyle}" ActivateCommand="{Binding DevCommand}/>
</igDP:Field.Settings>
</igDP:Field>
I dont really care if the command has to be a property of my viewmodel or the dataitem.
How do i implement this?
Thank You
Attached Behavior and MVVM goes hand in hand.
Handle your event via attached behavior and supply Viewmodel.ICommand to it, which it would execute when the event is handled. You can then send the event args from the handled event across to the ViewModel.ICommand as command parameter.
Your attached property
public static class MyBehaviors {
public static readonly DependencyProperty CellActivatedCommandProperty
= DependencyProperty.RegisterAttached(
"CellActivatedCommand",
typeof(ICommand),
typeof(MyBehaviors),
new PropertyMetadata(null, OnCellActivatedCommandChanged));
public static ICommand CellActivatedCommand(DependencyObject o)
{
return (ICommand)o.GetValue(CellActivatedCommandProperty);
}
public static void SetCellActivatedCommand(
DependencyObject o, ICommand value)
{
o.SetValue(CellActivatedCommandProperty, value);
}
private static void OnCellActivatedCommandChanged(
DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
var xamDataGrid = d as XamDataGrid;
var command = e.NewValue as ICommand;
if (xamDataGrid != null && command != null)
{
xamDataGrid.CellActivated +=
(o, args) =>
{
command.Execute(args);
};
}
}
}
Your XAML:
<infragistics:XamDataGrid ...
local:MyBehaviors.CellActivatedCommand="{Binding MyViewModelCommand}" />
Hope it helps.

WPF- Problem with TextBox in DataTemplate

I am working on an application where Repository objects are displayed via a DataTemplate that contains a modified version of a TextBox, which supports binding to the SelectionStart, SelectionLength, and VerticalOffset.
The DataTemplate looks like this:
<DataTemplate DataType="{x:Type m:Repository}">
<controls:ModdedTextBox
x:Name="textBox" Text="{Binding Text, UpdateSourceTrigger=PropertyChanged}"
BindableSelectionStart="{Binding SelectionStart, UpdateSourceTrigger=PropertyChanged}"
BindableSelectionLength="{Binding SelectionLength, UpdateSourceTrigger=PropertyChanged}"
BindableVerticalOffset="{Binding VerticalOffset, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</DataTemplate>
The problem is that when I change the Repositorythat is currently being displayed; the SelectionStart, SelectionLength, and VerticalOffset all seem to be getting set to 0, even when those properties of the Repository object are not 0.
I think that this is happening in the instant before the text is displayed when the SelectionStart, SelectionLength, and VerticalOffset can not be more than 0. This does not only set the actual properties of the TextBox to zero, but also updates the bindings and sets the properties of the Repository object to zero.
Is there any way that I can prevent this from happening?
--Edit--
I don't know if posting dl links to projects is a no-no or not on SO, but here is a link to a project I created to demonstrate the problem I am having: http://dl.dropbox.com/u/1520079/RepositoryProblemDemo.zip
When you run the demo-app the selection you can click the "Switch Repository" button to change the repository that is displayed in the textbox. If you look to the right of the textbox the current repository's properties all get set to zero when you switch to the other one.
A difference between this demo and my actual app is that in my app repositories will be switched via hotkeys, not a button.
The problem is due to the fact that the bindings are evaluated in serial, and when the Text property is changed it causes all selection information to be removed (you can see this by putting breakpoints on your ModdedTextBox event handlers). As the BindableSelection... bindings are still active at that point, it causes the selection information to be reset.
Depending on the exact behaviour you want there is probably a way to work around this, but you would need to know a little more detail...
Edit in response to comments:
This solution isn't exactly answering your original question, and it probably isn't great practice, but it does at least work...
Try altering your ModdedTextBox so that instead of exposing bindable properties for the selection information, expose a single DP of type Repository and bind to that:
<local:ModdedTextBox
x:Name="textBox"
Repository="{Binding CurrentRepository}"
TextWrapping="Wrap"
/>
Then handle the changed event on your DP to set the text box properties:
public static DependencyProperty RepositoryProperty =
DependencyProperty.Register("Repository",
typeof(Repository), typeof(ModdedTextBox), new PropertyMetadata(null, OnRepositoryChanged));
public Repository Repository
{
get { return (Repository)base.GetValue(RepositoryProperty); }
set { base.SetValue(RepositoryProperty, value); }
}
private static void OnRepositoryChanged(DependencyObject senderObject, DependencyPropertyChangedEventArgs e)
{
var sender = (ModdedTextBox)senderObject;
var oldRepository = e.OldValue as Repository;
var newRepository = e.NewValue as Repository;
if (oldRepository != null)
{
oldRepository.Text = sender.Text;
oldRepository.SelectionStart = sender.SelectionStart;
//etc
}
if (newRepository != null)
{
sender.Text = newRepository.Text;
sender.SelectionStart = newRepository.SelectionStart;
//etc
}
}
This is essentially removing the serial nature of the binding evaluation.
Note: You could also achieve the same using attached properties, which would be better than subclassing TextBox, but this is closer to your original attempts so I figure its easier to explain!
Here is a re-write of the other solution. This one takes into account the text property not being bound before the other properties.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
namespace WpfApplication1
{
public class SelectionBindingTextBox : TextBox
{
public static readonly DependencyProperty BindableSelectionStartProperty =
DependencyProperty.Register(
"BindableSelectionStart",
typeof(int),
typeof(SelectionBindingTextBox),
new PropertyMetadata(OnBindableSelectionStartChanged));
public static readonly DependencyProperty BindableSelectionLengthProperty =
DependencyProperty.Register(
"BindableSelectionLength",
typeof(int),
typeof(SelectionBindingTextBox),
new PropertyMetadata(OnBindableSelectionLengthChanged));
private bool isBindingComplete = false;
public SelectionBindingTextBox()
: base()
{
this.SelectionChanged += this.OnSelectionChanged;
this.TextChanged += this.OnTextChanged;
}
public int BindableSelectionStart
{
get
{
return (int)this.GetValue(BindableSelectionStartProperty);
}
set
{
this.SetValue(BindableSelectionStartProperty, value);
}
}
public int BindableSelectionLength
{
get
{
return (int)this.GetValue(BindableSelectionLengthProperty);
}
set
{
this.SetValue(BindableSelectionLengthProperty, value);
}
}
private static void OnBindableSelectionStartChanged(DependencyObject dependencyObject,
DependencyPropertyChangedEventArgs args)
{
var textBox = dependencyObject as SelectionBindingTextBox;
if (textBox.isBindingComplete)
{
textBox.SetupSelection();
}
}
private static void OnBindableSelectionLengthChanged(DependencyObject dependencyObject,
DependencyPropertyChangedEventArgs args)
{
var textBox = dependencyObject as SelectionBindingTextBox;
if (textBox.isBindingComplete)
{
textBox.SetupSelection();
}
}
private void OnSelectionChanged(object sender, RoutedEventArgs e)
{
if (isBindingComplete)
{
this.BindableSelectionStart = this.SelectionStart;
this.BindableSelectionLength = this.SelectionLength;
}
}
private void OnTextChanged(object sender, RoutedEventArgs e)
{
if (!isBindingComplete)
{
SetupSelection();
}
isBindingComplete = true;
}
private void SetupSelection()
{
// this.Focus();
this.SelectionLength = this.BindableSelectionLength;
this.SelectionStart = this.BindableSelectionStart;
}
}
}
Well update of binding depends on the order in which WPF or Silverlight Engine will evaluate, looks like your SelectionStart and SelectionEnd bindings are updated before Text, so when Text gets changed, SelectionStart and SelectionEnd are both changed back to zero.
The only way is to hook for TextChanged event and refresh the bindings of SelectionStart and SelectionEnd or in WPF you can extend textbox as follow
public class MyTextBox : TextBox{
protected override OnTextChanged(TextChangedEventArgs e){
BindingExpression be = this.GetBindingExpression(SelectionStartProperty);
if(be!=null){
be.UpdateTarget();
}
be = this.GetBindingExpression(SelectionEndProperty);
if(be!=null){
be.UpdateTarget();
}
be = this.GetBindingExpression(VerticalOffsetProperty);
if(be!=null){
be.UpdateTarget();
}
}
}
Well here there is a trick, you still have to change above logic to fit in your logic because everytime text updates this will update binding, so you have to find out when to refresh these bindings. Because this will consistantly fail to change your textbox's value in runtime as text will modify and selection will goto previous selection only.

How to bind to a custom property in a Silverlight Custom control

I've created a custom control with, amongst others, the following:
public partial class MyButton : UserControl
{
public bool Enabled
{
get { return (bool)GetValue(EnabledProperty); }
set {
SetValue(EnabledProperty, value);
SomeOtherStuff();
}
}
}
public static readonly DependencyProperty EnabledProperty =
DependencyProperty.Register("Enabled", typeof(bool), typeof(MyButton), new PropertyMetadata(true));
public static void SetEnabled(DependencyObject obj, bool value)
{
obj.SetValue(EnabledProperty, value);
}
public static bool GetEnabled(DependencyObject obj)
{
return (bool) obj.GetValue(EnabledProperty);
}
}
In my XAML, I (try to) use binding to set the Enabled property:
<MyButton x:Name="myButtom1" Enabled="{Binding CanEnableButton}"/>
I know the bind between my control and the underlying data model is valid and working as I can bind 'IsEnabled' (a native property of the underlying UserControl) and it works as expected. However, my Enabled property is never set via the above binding. I've put breakpoints on my property set/get and they never get hit at all.
I can only imaging I've missed something relating to binding in my custom control. Can anyone see what?
I've tried implementing INotifyPropertyChanged on my control (and calling the PropertyChanged event from my Enabled setter) ... but that didn't fix it.
[ BTW: In case you are wondering "Why?": I can't intercept changes to the IsEnabled state of the base control, so I decided to implement and use my own version of a Enable/disable property (which I called Enabled) - one where I could plug my own code into the property setter ]
First of all drop the SetEnabled and GetEnabled pair, these only make sense for an attached property which is not what you are doing.
Now your main problem is that you are under the false assumption that the get/set members of your propery get called during binding, they don't.
What you need is to pass a call back method in the property meta data, it's here that you intercept changes and take other actions like so:-
public bool IsEnabled
{
get { return (bool)GetValue(IsEnabledProperty); }
set { SetValue(IsEnabledProperty, value); }
}
public static readonly DependencyProperty IsEnabledProperty =
DependencyProperty.Register(
"IsEnabled",
typeof(bool),
typeof(MyButton),
new PropertyMetadata(true, OnIsEnabledPropertyChanged));
private static void OnIsEnabledPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
MyButton source = d as MyButton;
source.SomeOtherStuff();
}
private void SomeOtherStuff()
{
// Your other stuff here
}
With this in place regardless of how the propery is changed the SomeOtherStuff procedure will execute.
I'd suggest using the IsEnabledChanged event which is part of every Control/UserControl.
That would allow you to hook up to the event and do whatever actions you want to take.
public MainPage()
{
InitializeComponent();
this.IsEnabledChanged += new DependencyPropertyChangedEventHandler(MainPage_IsEnabledChanged);
}
void MainPage_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
{
// Do SomeStuff
}

WPF, getting two way binding to work on custom control

Two way binding does not work on my custom control with the following internals:
public partial class ColorInputControl
{
public ColorInputControl()
{
InitializeComponent();
colorPicker.AddHandler(ColorPicker.SelectedColorChangedEvent,
new RoutedPropertyChangedEventHandler<Color>( SelectedColorChanged));;
colorPicker.AddHandler(ColorPicker.CancelEvent,
new RoutedPropertyChangedEventHandler<Color>(OnCancel));
}
public static readonly DependencyProperty SelectedColorProperty =
DependencyProperty.Register
("SelectedColor", typeof(Color), typeof(ColorInputControl),
new PropertyMetadata(Colors.Transparent, null));
public Color SelectedColor
{
get
{
return (Color)GetValue(SelectedColorProperty);
//return colorPicker.SelectedColor;
}
set
{
SetValue(SelectedColorProperty, value);
colorPicker.SelectedColor = value;
}
}
private void SelectedColorChanged(object sender, RoutedPropertyChangedEventArgs<Color> e)
{
SetValue(SelectedColorProperty, colorPicker.SelectedColor);
}
}
SelectedColor is being bound to a property that fires INotifyPropertyChanged event control when it changes. However, I cannot get two-way binding to work. Changes from the UI are pesisted to the data source. However, changes originating from the data source are not reflected on the UI.
What did I miss? TIA.
Never do any work (updating the color picker) in the SelectColor helpers. Those are convinence wrappers and are not guarranted to be called. (As you can see in your two way binding.) Add a PropertyChangedCallback to your SelectedColorProperty metadata. Do your work in there.

binding element focus with an attached property?

I'm trying to bind focus for my control to a property on the view model, like this:
public class Focus
{
public static readonly DependencyProperty HasFocusProperty = DependencyProperty.RegisterAttached("HasFocus",
typeof(bool),
typeof(Focus),
new PropertyMetadata(false, HandleHasFocusChanged),
null
);
private static void HandleHasFocusChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var uiElement = d as UIElement;
var value = (bool)e.NewValue;
if (value)
{
FocusManager.SetFocusedElement(uiElement, uiElement);
}
}
public static bool GetHasFocus(UIElement obj)
{
return (bool)obj.GetValue(HasFocusProperty);
}
public static void SetHasFocus(UIElement obj, bool value)
{
obj.SetValue(HasFocusProperty, value);
}
}
This works for the first focus, but then after that it seems to not have any affect at all
Anybody know what I'm doing wrong, or even a better way to do what I'm trying to achieve?
Probably the difference between logical focus and keyboardfocus is biting you. You can read about it here. Pay particular attention to the part about focus scope.
You have implemented code to set the logical focus to your user control when the HasFocus property is set to true, but you do nothing when it is set to false. In that case the logical focus will stay where it is.
On the other hand, you have not hooked up an event handler for the user control's lostfocus event. That means that your HasFocus property will once more be unaffected when the control loses focus.

Resources