Can I bind a ReactiveCommand to MouseDown event on Textbox? - wpf

I'm trying to get the WPF ReactiveUI framework's new view ctor binding to bind a ReactiveCommand that is working on a Button click to wire up to a TextBox MouseDown/click event. The following doesn't work.
public partial class KeypadNumberView
: IKeypadNumberView
, IViewFor<IOnScreenKeyboard>
{
public KeypadNumberView()
{
ViewModel = new KeyboardViewModel();
InitializeComponent();
this.Bind(ViewModel, x => x.EnteredText);
this.BindCommand(ViewModel, vm => vm.Delete, v => v.EnteredText, "MouseDown" ); // doesn't work
this.BindCommand(ViewModel, vm => vm.Delete); // <== works

That seems like it should work. Can you file a bug at http://github.com/reactiveui/reactiveui ?

Related

Observable for System.Windows.Point

I added property in View:
[Reactive] public Point PositionLeftClick { get; set; } = new Point();
On mouse click I set property value.
And try use it as parameter for command parameter
this.WhenActivated(disposable =>
{
var positionLeftClickObservable = this.WhenAnyValue(x => x.PositionLeftClick);
this.BindCommand(this.ViewModel, x => x.CommandAddNodeWithUndoRedo, x => x.ItemAddNode,
positionLeftClickObservable).DisposeWith(disposable);
});
But parameter value in command always 0,0
How I can fix it?
Generally, I wouldn't put a [Reactive] property in a View. Normally I would delegate that to some ViewModel and bind it to the View.
ReactiveUI is an MVVM framework, and it works better when you provide a ViewModel for binding state to the View.

How to bind command using ReactiveUI and WPF

I'm trying to learn ReactiveUI in WPF and I'm confusing on how to bind command using Reactive UI binding (not default Xaml binding).
I read on ReactiveUI documentation that the correct way is to use the following instruction:
this.BindCommand(this.ViewModel, vm => vm.MyCommand, v => v.myControl);
Now if I have in MainWindowView.xaml (View):
<Button x:Name="TestButton" Command="{Binding Click}" />
in MainWindowView code-behind:
public partial class MainWindowView : Window
{
public MainWindowView()
{
InitializeComponent();
DataContext = new MainWindowViewModel();
}
}
and in MainWindowViewModel (ViewModel):
class MainWindowViewModel : ReactiveObject
{
public ReactiveCommand<Unit, Unit> ClickCommand { get; }
public MainWindowViewModel()
{
ClickCommand = ReactiveCommand.Create(ClickMethod);
}
void ClickMethod()
{
// Code for executing the command here.
}
}
I don't know where insert and how to compose the first instruction :
this.BindCommand(this.ViewModel, vm => vm.MyCommand, v => v.myControl);
for my specific context.
Thank you very much for and an answer.
The WPF samples referenced by Rodney Littles in the comment above are very good. For your case it should be something like this:
public partial class MainWindowView : ReactiveWindow<MainWindowViewModel>
{
public MainWindowView()
{
InitializeComponent();
ViewModel = new MainWindowViewModel();
this
.WhenActivated(disposables => {
this
.BindCommand(this.ViewModel, vm => vm.ClickCommand, v => v.TestButton)
.DisposeWith(disposables);
});
}
}
Make sure you derive from ReactiveWindow<MainWindowViewModel> instead of Window. Also, instead of DataContext, use the inherited property named ViewModel.

Set Focus OnNavigatedTo in Prism for WPF Application

I would like on navigation between views in a WPF application using Prism to have the ability to set focus to sepecific textboxes so a user can perform navigation and then begin typing in the relevant textbox without a second click into the textbox.
I have an application built with Prism that has a Shell with a ContentControl "MainContentRegionContentControl". I then have some buttons across the top when on clicking them I do a region.RequestNavigate("UserControlToLoad"). On the UserControl I have the OnNavigatedTo and in that method I call this.MainTextBox.Focus().
The above doesn't appear to work, the navigation appears to work and the OnNavigatedTo method is called, but the textbox doesn't have focus.
I've added FocusManager.IsFocusScope="True" to the textbox, but this hasn't made a difference.
Use Loaded() method for each page instead of OnNavigatedTo() and TextBox.Focus() will work fine then ;)
Try the following... In your View implement IActiveAware
class ViewModel : IActiveAware
{
#region IActiveAware Members
private bool isActive = false;
public bool IsActive
{
get
{
return isActive;
}
set
{
if (value != isActive)
{
isActive = value;
OnIsActiveChanged(EventArgs.Empty);
}
}
}
public event EventHandler IsActiveChanged = delegate { };
protected virtual void OnIsActiveChanged(EventArgs args)
{
IsActiveChanged(this, args);
}
#endregion
}
OnIsActiveChanged, try setting focus to the TextBox you'd like to focus when IsActive becomes true

Window doesn't update when ViewModel is changed

I have a WPF application using MVVM; when I change the ViewModel in my main window ViewModel class, the new user control is not displayed in the window... the original one remains. The ViewModel looks like this:
public class MainWindowViewModel : ViewModelBase
{
public ViewModelBase Workspace;
public MainWindowViewModel()
{
var w = new CustomerDetailsViewModel();
SetActiveWorkspace(w);
}
void NavigationService_ViewChanged(object sender, ViewChangedEventArgs e)
{
SetActiveWorkspace(e.View);
}
void SetActiveWorkspace(ViewModelBase workspace)
{
Workspace = workspace;
}
}
My XAML looks like this:
< ContentControl Content="{Binding Path=Workspaces}" >
The navigation service ViewChanged event is firing, and the SetActiveWorkspace method is being called with the correct view in the argument. However, after that, the view is not reloaded. What am I missing here?
Your Workspace property is not raising the PropertyChanged event. It should look like this:
private ViewModelBase _workspace;
public ViewModelBase Workspace
{
get { return _workspace; }
set
{
if (value != _workspace)
{
_workspace = value;
// This raises the PropertyChanged event to let the UI know to update
OnPropertyChanged("WorkSpace");
}
}
}
Make sure your ViewModelBase implements INotifyPropertyChanged

How to close a ChildWindow with Cancel button using MVVM Light Toolkit

I'm new to MVVM and trying to figure out how to close a ChildWindow with the traditional Cancel button using MVVM Light Toolkit.
In my ChildWindow (StoreDetail.xaml), I have :
<Button x:Name="CancelButton" Content="Cancel" Command="{Binding CancelCommand}" />
In my ViewModel (ViewModelStoreDetail.cs), I have :
public ICommand CancelCommand { get; private set; }
public ViewModelStoreDetail()
{
CancelCommand = new RelayCommand(CancelEval);
}
private void CancelEval()
{
//Not sure if Messenger is the way to go here...
//Messenger.Default.Send<string>("ClosePostEventChildWindow", "ClosePostEventChildWindow");
}
private DelegateCommand _cancelCommand;
public ICommand CancelCommand
{
get
{
if (_cancelCommand == null)
_cancelCommand = new DelegateCommand(CloseWindow);
return _cancelCommand;
}
}
private void CloseWindow()
{
Application.Current.Windows[Application.Current.Windows.Count - 1].Close();
}
If you displayed your child window by calling ShowDialog(), then you can simply set the IsCancel property of your button control to "True".
<Button Content="Cancel" IsCancel="True" />
It becomes the same as clicking the X button on the window, or pressing ESC on the keyboard.
Have a look at this articleon MSDN. About half way down there is an approach on how to do this. Basically it uses either uses a WorkspaceViewModel or you implements an interface that exposes and event RequestClose
You then inside the Window's DataContext (if you are setting the ViewModel to it) you can attach to the event.
This is an excerpt from the article (Figure 7). You can adjust it to suit your needs.
// In App.xaml.cs
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
MainWindow window = new MainWindow();
// Create the ViewModel to which
// the main window binds.
string path = "Data/customers.xml";
var viewModel = new MainWindowViewModel(path);
// When the ViewModel asks to be closed,
// close the window.
viewModel.RequestClose += delegate
{
window.Close();
};
// Allow all controls in the window to
// bind to the ViewModel by setting the
// DataContext, which propagates down
// the element tree.
window.DataContext = viewModel;
window.Show();
}
It's been a while since I've used WPF and MVVMLight but yes I think I'd use the messanger to send the cancel event.
In MVVM Light Toolkit the best what you can do is to use Messenger to interact with the View.
Simply register close method in the View (typically in the code behind file) and then send request to close a window when you need it.
We have implemented a NO-CODE BEHIND functionality. See if it helps.
EDIT: Here is there Stackoverflow discussion
Here are some ways to accomplish it.
Send message to your childwindow and set DialogueResult to false on childwindow code-behind.
Make property of DialogueResult and Bind it with childwindow Dialoue CLR property, set it on CancelEval method of CancelCommand.
Create object of Childwindow and set DialogueResult false on CancelEval.
Kind of late to the party but I thought I'd add my input. Borrowing from user841960's answer:
public RelayCommand CancelCommand
{
get;
private set;
}
Then:
SaveSettings = new RelayCommand(() => CloseWindow());
Then:
private void CloseWindow()
{
Application.Current.Windows[Application.Current.Windows.Count - 1].Close();
}
It's a bit cleaner than using an ICommand and works just as well.
So, to sum it all up, the example class would look like so:
public class ChildViewModel
{
public RelayCommand CancelCommand
{
get;
private set;
}
public ChildViewModel()
{
SaveSettings = new RelayCommand(() => CloseWindow());
}
private void CloseWindow()
{
Application.Current.Windows[Application.Current.Windows.Count - 1].Close();
}
}

Resources