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.
Related
I am not sure if this is an MVVM-Light bug or just something that doesn't work in WPF.... I have a button where I am setting the Command property to a RelayCommand. Everything works fine as long as I don't set the CommandParameter property. Once I do, the CanExecute callback quits working.
I am using the GalaSoft.MvvmLight.CommandWpf namespace as I am working in .Net 4.5.2. Here is a code snippit:
public RelayCommand<IList> SetFlagCommand { get; private set; }
...
SetFlagCommand = new RelayCommand<IList>(SetFlag, CanSetFlag);
...
mButtons.Add(new Button
{
...
Command = SetFlagCommand,
CommandParameter = new Binding("SelectedItems") { ElementName = "lstAllChoices" },
});
...
private void SetFlag(IList list)...
private bool CanSetFlag(IList list)...
The CanSetFlag method is called once, but then never again. If I don't set the CommandParameter property, it works as expected. Any ideas what is going on?
Thanks for any help!
You are not supposed to set the CommandParameter property to a Binding. Bind it using the BindingOperations.SetBinding method instead:
Button button = new Button()
{
Command = SetFlagCommand
};
BindingOperations.SetBinding(button, Button.CommandParameterProperty, new Binding("SelectedItems") { ElementName = "lstAllChoices" });
mButtons.Add(btn);
Also make sure that the type of the source property (SelectedItems) matches the type parameter T of the RelayCommand<T>.
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 ?
How can I know that some property was binding?
For example a property (Class implemeted from NotificationObject):
public string Title
{
set
{
_title=value;
this.RaisePropertyChanged(() => this.Title);
}
get
{
return _title;
}
}
Using:
<TextBlock Text={Binding Title}>
I need to know when a property is not used by anyone to release dispose resources.
There's no easy way to know if a control is bound to a specific property of your ViewModel, but you can know if someone is subscribed to the PropertyChanged event (just check if it's not null). The binding engines subscribes to this event, so if something is bound to at least one property of your ViewModel, the PropertyChanged event handler won't be null.
You can tell if someone has requested your property by setting a flag, although not sure if this will meet your needs:
private bool _isTitleBound = false;
public string Title
{
set
{
_title = value;
this.RaisePropertyChanged(() => Title);
}
get
{
_isTitleBound = true;
return _title;
}
}
You could also consider lazy instantiation, which would result in your disposable objects only being created when the property getter was called. If the property getters are never called, your disposable objects will never be created. Also, if this is a one-time binding consider using lazy instantiation with disposal of your object. For example:
public MyThing Thing
{
get
{
MyThing thing = CreateMyThing();
Dispatcher.CurrentDispatcher.BeginInvoke(
DispatcherPriority.Background,
new Action(() => thing.Dispose());
return thing;
}
}
private MyThing CreateMyThing()
{
//create and return MyThing instance;
}
How do I add a custom convention to Caliburn.Micro for the IsEnabled property of controls - something like having NameEnabled bound to IsEnabled in parallel to Name bound to Text on a TextBox.
In a way, what I want to achieve is similar to the way that a CanSave property can be used to enable/disable a button bound to a Save method, but generic for all controls.
Caliburn.Micro right now (1.3.1) doesn't really support this "multiple" conventions for the same FrameworkElement, what you have described.
EDIT:
However you can hook into the ViewModelBinder.BindProperties method and there you can implement your own extra convetion.
I went one step further and implemented a prototype which works, but it's not robust, nor elegant and probably not the correct way to do this. But it can be a starting point:
static AppBootstrapper()
{
ConventionManager.AddElementConvention<FrameworkElement>(
UIElement.IsEnabledProperty,
"IsEnabled",
"IsEnabledChanged");
var baseBindProperties = ViewModelBinder.BindProperties;
ViewModelBinder.BindProperties =
(frameWorkElements, viewModels) =>
{
foreach (var frameworkElement in frameWorkElements)
{
var propertyName = frameworkElement.Name + "Enabled";
var property = viewModels
.GetPropertyCaseInsensitive(propertyName);
if (property != null)
{
var convention = ConventionManager
.GetElementConvention(typeof(FrameworkElement));
ConventionManager.SetBindingWithoutBindingOverwrite(
viewModels,
propertyName,
property,
frameworkElement,
convention,
convention.GetBindableProperty(frameworkElement));
}
}
return baseBindProperties(frameWorkElements, viewModels);
};
}
You can enable/disable a control by setting a boolean property in your ViewModel and you just bind to IsEnabled in XAML:
TextBox Name="SerialNumber" IsEnabled="{Binding IsReadOnly}"...
ViewModel:
private bool isReadOnly;
public bool IsReadOnly
{
get { return isReadOnly; }
set
{
this.isReadOnly = value;
NotifyOfPropertyChange( () => IsReadOnly);
}
}
I have an INotifyProperty Screen item that I have bound to a wpf control.
Ok... I Simplified everything and am posting more code. I have a MainViewModel with the selected screen property.
public Screen SelectedScreen
{
get { return this.selectedScreen; }
set
{
this.selectedScreen = value;
this.OnPropertyChanged("SelectedScreen");
}
}
I have a textbox that is bound to this property:
<TextBlock Text="{Binding Path=SelectedScreen.ScreenNumber}" />
This all works initially. I have created another control that is changing the selected screen with the following code.
public Screen SelectedScreen
{
get { return (Screen)GetValue(SelectedScreenProperty); }
set
{
this.SetValue(SelectedScreenProperty, value);
for (int x = 0; x < this.Screens.Count; ++x)
this.Screens[x].IsSelected = false;
value.IsSelected = true;
}
}
public ObservableCollection<Screen> Screens
{
get { return (ObservableCollection<Screen>)GetValue(ScreensProperty); }
set { this.SetValue(ScreensProperty, value); }
}
public static readonly DependencyProperty SelectedScreenProperty =
DependencyProperty.Register("SelectedScreen",
typeof(Screen),
typeof(ScreenSelection));
public static readonly DependencyProperty ScreensProperty =
DependencyProperty.Register("Screens",
typeof(ObservableCollection<Screen>),
typeof(ScreenSelection),
new UIPropertyMetadata(new ObservableCollection<Screen>()));
This screen selection control is working. When I change screens and put a breakpoint on the set property of SelectedScreen it is called which then calls the SelectedScreen property of the MainViewModel. So the event is firing, but the textbox isn't updated even though it binds correctly the first time.
Does the class which contains the SelectedScreen property implement INotifyPropertyChanged? When the SelectedScreen property changes, the containing class should raise the PropertyChanged event, and typically, WPF should update the Binding.
Thank you gehho for looking at this. I figured it out and there is no way you had enough information to be able too. I was inheriting from ViewModelBase in the MainViewModel that was inheriting from ObservableObject where I implemented INotifyPropertyChanged. The problem is that I implemented the methods for INotifyPropertyChanged in both classes and WPF was listening to the wrong one. Very obscure. Very annoying. Very lasjkdf;ashdoh