I try to use this xaml, to apply an event to command binding:
<telerik:RadGridView x:Name="xRadGridView"
prismcommands:SelectionChangedCommand.Command="{Binding SelectPersonCommand}"
ItemsSource="{Binding GridItems, Mode=TwoWay}">
</telerik:RadGridView>
I get the error:
'SelectionChangedCommand.Command' property is read-only and cannot be
set from markup.
I can bind to prismcommands:RowEditEndedCommand.Command with no problem.
Is there any chance to bind to SelectionChangedCommand.Command?
I use the same PrismCommands in a Silverlight project and it works there.
namespace RadEventToCommand.WPF.PrismCommands
{
public class RowEditEndedCommandBehavior : CommandBehaviorBase<RadGridView>
{
public RowEditEndedCommandBehavior(RadGridView gridView)
: base(gridView)
{
gridView.RowEditEnded +=new EventHandler<GridViewRowEditEndedEventArgs>(gridView_RowEditEnded);
}
void gridView_RowEditEnded(object sender, GridViewRowEditEndedEventArgs e)
{
CommandParameter = e;
ExecuteCommand();
}
}
}
--
namespace RadEventToCommand.WPF.PrismCommands
{
public static class SelectionChangedCommand
{
private static readonly DependencyProperty SelectionChangedCommandBehaviorProperty
= DependencyProperty.RegisterAttached(
"SelectionChangedCommandBehavior",
typeof(SelectionChangedCommandBehavior),
typeof(SelectionChangedCommand),
null);
public static readonly DependencyProperty CommandProperty
= DependencyProperty.RegisterAttached(
"Command",
typeof(ICommand),
typeof(SelectionChangedCommand),
new PropertyMetadata(OnSetCommandCallback));
public static readonly DependencyProperty CommandParameterProperty
= DependencyProperty.RegisterAttached(
"CommandParameter",
typeof(object),
typeof(SelectionChangedCommand),
new PropertyMetadata(OnSetCommandParameterCallback));
public static ICommand GetCommand(RadGridView gridView)
{
return gridView.GetValue(CommandProperty) as ICommand;
}
public static void SetCommandParameter(RadGridView gridView, object parameter)
{
gridView.SetValue(CommandParameterProperty, parameter);
}
public static object GetCommandParameter(RadGridView gridView)
{
return gridView.GetValue(CommandParameterProperty);
}
private static void OnSetCommandCallback
(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
RadGridView gridView = dependencyObject as RadGridView;
if (gridView != null)
{
SelectionChangedCommandBehavior behavior = GetOrCreateBehavior(gridView);
behavior.Command = e.NewValue as ICommand;
}
}
private static void OnSetCommandParameterCallback
(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
RadGridView gridView = dependencyObject as RadGridView;
if (gridView != null)
{
SelectionChangedCommandBehavior behavior = GetOrCreateBehavior(gridView);
behavior.CommandParameter = e.NewValue;
}
}
private static SelectionChangedCommandBehavior GetOrCreateBehavior(RadGridView gridView)
{
SelectionChangedCommandBehavior behavior =
gridView.GetValue(SelectionChangedCommandBehaviorProperty) as SelectionChangedCommandBehavior;
if (behavior == null)
{
behavior = new SelectionChangedCommandBehavior(gridView);
gridView.SetValue(SelectionChangedCommandBehaviorProperty, behavior);
}
return behavior;
}
}
}
--
namespace RadEventToCommand.WPF.PrismCommands
{
public class RowEditEndedCommandBehavior : CommandBehaviorBase<RadGridView>
{
public RowEditEndedCommandBehavior(RadGridView gridView)
: base(gridView)
{
gridView.RowEditEnded +=new EventHandler<GridViewRowEditEndedEventArgs>(gridView_RowEditEnded);
}
void gridView_RowEditEnded(object sender, GridViewRowEditEndedEventArgs e)
{
CommandParameter = e;
ExecuteCommand();
}
}
}
--
namespace RadEventToCommand.WPF.PrismCommands
{
public static class RowEditEndedCommand
{
private static DependencyProperty RowEditEndedCommandBehaviorProperty
= DependencyProperty.RegisterAttached(
"RowEditEndedCommandBehavior",
typeof(RowEditEndedCommandBehavior),
typeof(RowEditEndedCommand),
null);
public static DependencyProperty CommandProperty
= DependencyProperty.RegisterAttached(
"Command",
typeof(ICommand),
typeof(RowEditEndedCommand),
new PropertyMetadata(OnSetCommandCallback));
public static DependencyProperty CommandParameterProperty
= DependencyProperty.RegisterAttached(
"CommandParameter",
typeof(object),
typeof(RowEditEndedCommand),
new PropertyMetadata(OnSetCommandParameterCallback));
public static ICommand GetCommand(RadGridView gridView)
{
return gridView.GetValue(CommandProperty) as ICommand;
}
public static void SetCommand(RadGridView gridView, object parameter)
{
gridView.SetValue(CommandProperty, parameter);
}
public static void SetCommandParameter(RadGridView gridView, object parameter)
{
gridView.SetValue(CommandParameterProperty, parameter);
}
public static object GetCommandParameter(RadGridView gridView)
{
return gridView.GetValue(CommandParameterProperty);
}
private static void OnSetCommandCallback
(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
RadGridView gridView = dependencyObject as RadGridView;
if (gridView != null)
{
RowEditEndedCommandBehavior behavior = GetOrCreateBehavior(gridView);
behavior.Command = e.NewValue as ICommand;
}
}
private static void OnSetCommandParameterCallback
(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
RadGridView gridView = dependencyObject as RadGridView;
if (gridView != null)
{
RowEditEndedCommandBehavior behavior = GetOrCreateBehavior(gridView);
behavior.CommandParameter = e.NewValue;
}
}
private static RowEditEndedCommandBehavior GetOrCreateBehavior(RadGridView gridView)
{
RowEditEndedCommandBehavior behavior =
gridView.GetValue(RowEditEndedCommandBehaviorProperty) as RowEditEndedCommandBehavior;
if (behavior == null)
{
behavior = new RowEditEndedCommandBehavior(gridView);
gridView.SetValue(RowEditEndedCommandBehaviorProperty, behavior);
}
return behavior;
}
}
}
I had the source for the behavior copied over from a Silverlight project. It worked there. For some reason in WPF I need the additional method in SelectionChangedCommand
public static void SetCommand(RadGridView gridView, object parameter)
{
gridView.SetValue(CommandProperty, parameter);
}
I copied the code over to check if I could use a common codebase for Silverlight and WPF.
For the RadGridView, we are using the Interaction Triggers. The below code works for us.
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding SelectedItemChangedCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
Related
I have a behavior for Textbox:
// C#
public class DigitsOnlyBehavior : Behavior<UIElement>
{
public static readonly DependencyProperty IsDigitOnlyProperty =
DependencyProperty.RegisterAttached("IsDigitOnly",
typeof(bool), typeof(DigitsOnlyBehavior),
new FrameworkPropertyMetadata(false, OnIsDigitOnlyChanged));
public static bool GetIsDigitOnly(Control obj)
{
return (bool)obj.GetValue(IsDigitOnlyProperty);
}
public static void SetIsDigitOnly(Control obj, bool value)
{
obj.SetValue(IsDigitOnlyProperty, value);
}
private static void OnIsDigitOnlyChanged(object sender, DependencyPropertyChangedEventArgs e)
{
// ignoring error checking
var textBox = (TextBox)sender;
var isDigitOnly = (bool)(e.NewValue);
if (isDigitOnly)
textBox.PreviewTextInput += BlockNonDigitCharacters;
else
textBox.PreviewTextInput -= BlockNonDigitCharacters;
}
}
In xaml I do this:
<!-- XAML -->
<TextBox local:DigitsOnlyBehavior.IsDigitOnly="true" />
Question is why I must to type string false or true, instead choose from list False or True like for let's say IsEnabled property? It's possible to change that?
I am Using MVVM with WPF. i am halted in a way, i want your views about this. i am firing Mouse Events using MouseBehaviour.cs class , Is there any other way to handle Mouse Events in MVVM WPF
using System.Windows;
using System.Windows.Input;
namespace Lovatts.MouseBehaviours
{
public class MouseBehaviour
{
#region MouseUp
public static readonly DependencyProperty MouseUpCommandProperty =
DependencyProperty.RegisterAttached("MouseUpCommand", typeof(ICommand), typeof(MouseBehaviour), new FrameworkPropertyMetadata(new PropertyChangedCallback(MouseUpCommandChanged)));
private static void MouseUpCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
FrameworkElement element = (FrameworkElement)d;
element.MouseUp += element_MouseUp;
}
static void element_MouseUp(object sender, MouseButtonEventArgs e)
{
FrameworkElement element = (FrameworkElement)sender;
ICommand command = GetMouseUpCommand(element);
command.Execute(e);
}
public static void SetMouseUpCommand(UIElement element, ICommand value)
{
element.SetValue(MouseUpCommandProperty, value);
}
public static ICommand GetMouseUpCommand(UIElement element)
{
return (ICommand)element.GetValue(MouseUpCommandProperty);
}
#endregion
#region MouseDown
public static readonly DependencyProperty MouseDownCommandProperty =
DependencyProperty.RegisterAttached("MouseDownCommand", typeof(ICommand), typeof(MouseBehaviour), new FrameworkPropertyMetadata(new PropertyChangedCallback(MouseDownCommandChanged)));
private static void MouseDownCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
FrameworkElement element = (FrameworkElement)d;
element.MouseDown += element_MouseDown;
}
static void element_MouseDown(object sender, MouseButtonEventArgs e)
{
FrameworkElement element = (FrameworkElement)sender;
ICommand command = GetMouseDownCommand(element);
command.Execute(e);
}
public static void SetMouseDownCommand(UIElement element, ICommand value)
{
element.SetValue(MouseDownCommandProperty, value);
}
public static ICommand GetMouseDownCommand(UIElement element)
{
return (ICommand)element.GetValue(MouseDownCommandProperty);
}
#endregion
#region MouseLeave
public static readonly DependencyProperty MouseLeaveCommandProperty =
DependencyProperty.RegisterAttached("MouseLeaveCommand", typeof(ICommand), typeof(MouseBehaviour), new FrameworkPropertyMetadata(new PropertyChangedCallback(MouseLeaveCommandChanged)));
private static void MouseLeaveCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
FrameworkElement element = (FrameworkElement)d;
element.MouseLeave += new MouseEventHandler(element_MouseLeave);
}
static void element_MouseLeave(object sender, MouseEventArgs e)
{
FrameworkElement element = (FrameworkElement)sender;
ICommand command = GetMouseLeaveCommand(element);
command.Execute(e);
}
public static void SetMouseLeaveCommand(UIElement element, ICommand value)
{
element.SetValue(MouseLeaveCommandProperty, value);
}
public static ICommand GetMouseLeaveCommand(UIElement element)
{
return (ICommand)element.GetValue(MouseLeaveCommandProperty);
}
#endregion
#region MouseLeftButtonDown
public static readonly DependencyProperty MouseLeftButtonDownCommandProperty =
DependencyProperty.RegisterAttached("MouseLeftButtonDownCommand", typeof(ICommand), typeof(MouseBehaviour), new FrameworkPropertyMetadata(new PropertyChangedCallback(MouseLeftButtonDownCommandChanged)));
private static void MouseLeftButtonDownCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
FrameworkElement element = (FrameworkElement)d;
element.MouseLeftButtonDown += element_MouseLeftButtonDown;
}
static void element_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
FrameworkElement element = (FrameworkElement)sender;
ICommand command = GetMouseLeftButtonDownCommand(element);
command.Execute(e);
}
public static void SetMouseLeftButtonDownCommand(UIElement element, ICommand value)
{
element.SetValue(MouseLeftButtonDownCommandProperty, value);
}
public static ICommand GetMouseLeftButtonDownCommand(UIElement element)
{
return (ICommand)element.GetValue(MouseLeftButtonDownCommandProperty);
}
#endregion
#region MouseLeftButtonUp
public static readonly DependencyProperty MouseLeftButtonUpCommandProperty =
DependencyProperty.RegisterAttached("MouseLeftButtonUpCommand", typeof(ICommand), typeof(MouseBehaviour), new FrameworkPropertyMetadata(new PropertyChangedCallback(MouseLeftButtonUpCommandChanged)));
private static void MouseLeftButtonUpCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
FrameworkElement element = (FrameworkElement)d;
element.MouseLeftButtonUp += element_MouseLeftButtonUp;
}
static void element_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
FrameworkElement element = (FrameworkElement)sender;
ICommand command = GetMouseLeftButtonUpCommand(element);
command.Execute(e);
}
public static void SetMouseLeftButtonUpCommand(UIElement element, ICommand value)
{
element.SetValue(MouseLeftButtonUpCommandProperty, value);
}
public static ICommand GetMouseLeftButtonUpCommand(UIElement element)
{
return (ICommand)element.GetValue(MouseLeftButtonUpCommandProperty);
}
#endregion
#region MouseMove
public static readonly DependencyProperty MouseMoveCommandProperty =
DependencyProperty.RegisterAttached("MouseMoveCommand", typeof(ICommand), typeof(MouseBehaviour), new FrameworkPropertyMetadata(new PropertyChangedCallback(MouseMoveCommandChanged)));
private static void MouseMoveCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
FrameworkElement element = (FrameworkElement)d;
element.MouseMove += new MouseEventHandler(element_MouseMove);
}
static void element_MouseMove(object sender, MouseEventArgs e)
{
FrameworkElement element = (FrameworkElement)sender;
ICommand command = GetMouseMoveCommand(element);
command.Execute(e);
}
public static void SetMouseMoveCommand(UIElement element, ICommand value)
{
element.SetValue(MouseMoveCommandProperty, value);
}
public static ICommand GetMouseMoveCommand(UIElement element)
{
return (ICommand)element.GetValue(MouseMoveCommandProperty);
}
#endregion
#region MouseRightButtonDown
public static readonly DependencyProperty MouseRightButtonDownCommandProperty =
DependencyProperty.RegisterAttached("MouseRightButtonDownCommand", typeof(ICommand), typeof(MouseBehaviour), new FrameworkPropertyMetadata(new PropertyChangedCallback(MouseRightButtonDownCommandChanged)));
private static void MouseRightButtonDownCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
FrameworkElement element = (FrameworkElement)d;
element.MouseRightButtonDown += element_MouseRightButtonDown;
}
static void element_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
FrameworkElement element = (FrameworkElement)sender;
ICommand command = GetMouseRightButtonDownCommand(element);
command.Execute(e);
}
public static void SetMouseRightButtonDownCommand(UIElement element, ICommand value)
{
element.SetValue(MouseRightButtonDownCommandProperty, value);
}
public static ICommand GetMouseRightButtonDownCommand(UIElement element)
{
return (ICommand)element.GetValue(MouseRightButtonDownCommandProperty);
}
#endregion
#region MouseRightButtonUp
public static readonly DependencyProperty MouseRightButtonUpCommandProperty =
DependencyProperty.RegisterAttached("MouseRightButtonUpCommand", typeof(ICommand), typeof(MouseBehaviour), new FrameworkPropertyMetadata(new PropertyChangedCallback(MouseRightButtonUpCommandChanged)));
private static void MouseRightButtonUpCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
FrameworkElement element = (FrameworkElement)d;
element.MouseRightButtonUp += element_MouseRightButtonUp;
}
static void element_MouseRightButtonUp(object sender, MouseButtonEventArgs e)
{
FrameworkElement element = (FrameworkElement)sender;
ICommand command = GetMouseRightButtonUpCommand(element);
command.Execute(e);
}
public static void SetMouseRightButtonUpCommand(UIElement element, ICommand value)
{
element.SetValue(MouseRightButtonUpCommandProperty, value);
}
public static ICommand GetMouseRightButtonUpCommand(UIElement element)
{
return (ICommand)element.GetValue(MouseRightButtonUpCommandProperty);
}
#endregion
#region MouseWheel
public static readonly DependencyProperty MouseWheelCommandProperty =
DependencyProperty.RegisterAttached("MouseWheelCommand", typeof(ICommand), typeof(MouseBehaviour), new FrameworkPropertyMetadata(new PropertyChangedCallback(MouseWheelCommandChanged)));
private static void MouseWheelCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
FrameworkElement element = (FrameworkElement)d;
element.MouseWheel += new MouseWheelEventHandler(element_MouseWheel);
}
static void element_MouseWheel(object sender, MouseWheelEventArgs e)
{
FrameworkElement element = (FrameworkElement)sender;
ICommand command = GetMouseWheelCommand(element);
command.Execute(e);
}
public static void SetMouseWheelCommand(UIElement element, ICommand value)
{
element.SetValue(MouseWheelCommandProperty, value);
}
public static ICommand GetMouseWheelCommand(UIElement element)
{
return (ICommand)element.GetValue(MouseWheelCommandProperty);
}
#endregion
}
}
Here is my Xaml Code
<Window x:Class="Lovatts.MouseBehaviours.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:MouseBehaviours="clr-namespace:Lovatts.MouseBehaviours" x:Name="RibbonWindow"
Width="640" Height="480" DataContext="{Binding Main, Source={StaticResource Locator}}">
<Grid>
<Rectangle Width="100" Height="100" Fill="Blue" MouseBehaviours:MouseBehaviour.MouseUpCommand="{Binding MouseUpCommand}">
</Rectangle>
<Rectangle Width="100" Height="100" x:Name="Rectangle" Fill="Red" MouseBehaviours:MouseBehaviour.MouseUpCommand="{Binding MouseUpCommand}" Margin="75,109,457,241">
</Rectangle>
</Grid>
</Window>
MainViewModel.cs
using System.Windows.Input;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Windows;
namespace MouseBehaviours.ViewModel
{
public class MainViewModel : ViewModelBase
{
private RelayCommand _mouseUpCommand;
public RelayCommand MouseUpCommand
{
get
{
if (_mouseUpCommand == null) return _mouseUpCommand = new RelayCommand(param => ExecuteMouseUp((MouseEventArgs)param));
return _mouseUpCommand;
}
set { _mouseUpCommand = value; }
}
private void ExecuteMouseUp(MouseEventArgs e)
{
Console.WriteLine("Mouse Up : " + e.GetPosition((IInputElement)e.Source));
}
}
public class RelayCommand : ICommand
{
#region Fields
private readonly Action<object> _execute;
private readonly Predicate<object> _canExecute;
private string _displayText;
public static List<string> Log = new List<string>();
private Action<object> action;
#endregion // Fields
#region Constructors
/// <summary>
/// Creates a new command that can always execute.
/// </summary>
/// <param name="execute">The execution logic.</param>
public RelayCommand(Action<object> execute)
: this(execute, null)
{
}
/// <summary>
/// Creates a new command.
/// </summary>
/// <param name="execute">The execution logic.</param>
/// <param name="canExecute">The execution status logic.</param>
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
: this(execute, canExecute, "")
{
}
public RelayCommand(Action<object> execute, Predicate<object> canExecute, string displayText)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
_displayText = displayText;
}
public string DisplayText
{
get { return _displayText; }
set { _displayText = value; }
}
#endregion // Constructors
#region ICommand Members
[DebuggerStepThrough]
public bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute(parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter)
{
_execute(parameter);
}
#endregion // ICommand Members
}
//class MainViewModel
//{
//}
}
Instead of writing you own behavior and calling commands from it, you can leverage the EventTriggers and Interactivity to bind the event action to the command.
here is simple example of doing it
http://www.c-sharpcorner.com/Blogs/11789/example-of-eventtrigger-in-mvvm-application.aspx
as described in the example if you want to fire command on MouseUp event on your rectangle you can just do:
<Rectangle >
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseUp">
<i:InvokeCommandAction Command="{Binding MyCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Rectangle >
#harjeet you need to use the below structure for Image MouseUp i.e instead of using "Image" try to use "Hyperlink command property" in TextBlock:
<TextBlock Panel.ZIndex="990"
Canvas.Right="30"
Canvas.Left="498"
Canvas.Top="4">
<Hyperlink TextDecorations="None"
Command="{Binding CloseLoginSettingPopup}">
<Image Cursor="Hand"
x:Name="Pop2"
Source="/img/close1.png"
Height="40"
Width="40"
Panel.ZIndex="990"
Canvas.Right="30"
Canvas.Left="498"
Canvas.Top="4" />
</Hyperlink>
</TextBlock>
https://learn.microsoft.com/en-us/dotnet/api/system.windows.input.mouseaction
<Rectangle>
<Rectangle.InputBindings>
<MouseBinding MouseAction="LeftClick" Command="{Binding MyCommand}" />
</Rectangle.InputBindings>
</Rectangle>
I have usercontrol, and there is a DependencyProperty defined in it.
#region ImageUri
public static readonly DependencyProperty ImageUriProperty = DependencyProperty.Register(
"ImageUri",
typeof(string),
typeof(ScrollableCanvas),
new PropertyMetadata(new PropertyChangedCallback(ImageUriPropertyChangedCallback)));
private static void ImageUriPropertyChangedCallback(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
ScrollableCanvas main = sender as ScrollableCanvas;
if (main != null)
{
main.ImageUri = (string)e.NewValue;
}
}
public string ImageUri
{
get
{
return (string)GetValue(ImageUriProperty);
}
set
{
SetValue(ImageUriProperty, value);
UpdateImage();
}
}
#endregion
In the Xaml, I bind a value to it like this
<my:ScrollableCanvas Name="scrollableCanvas1" ImageUri="{Binding Path=LayerImage}" />
when I update the LayerImage in the viewmodel, the ImageUri property does not update.
Can some help on this? Thanks.
BTW: The value is updated when I set the LayerImage in the constructor of the viewmodel.
You shouldn't include your UpdateImage call in your setter, but rather in the property changed callback.
public static readonly DependencyProperty ImageUriProperty = DependencyProperty.Register(
"ImageUri",
typeof(string),
typeof(ScrollableCanvas),
new PropertyMetadata(new PropertyChangedCallback(ImageUriPropertyChangedCallback)));
private static void ImageUriPropertyChangedCallback(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
ScrollableCanvas main = sender as ScrollableCanvas;
if (main != null)
{
// Since ImageUri has already been called at this point, you can just update your image here...
main.UpdateImage();
}
}
public string ImageUri
{
get
{
return (string)GetValue(ImageUriProperty);
}
set
{
SetValue(ImageUriProperty, value);
}
}
Does anyone know how to make a custom ItemsSource?
What I want to do is to make an itemsSource to my own UserControl so that it could be bound by ObservableCollection<>.
Also, I could know Whenever the number of items in the itemsSource updated, so as to do further procedures.
Thank you so much.
You may need to do something like this in your control
public IEnumerable ItemsSource
{
get { return (IEnumerable)GetValue(ItemsSourceProperty); }
set { SetValue(ItemsSourceProperty, value); }
}
public static readonly DependencyProperty ItemsSourceProperty =
DependencyProperty.Register("ItemsSource", typeof(IEnumerable), typeof(UserControl1), new PropertyMetadata(new PropertyChangedCallback(OnItemsSourcePropertyChanged)));
private static void OnItemsSourcePropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
var control = sender as UserControl1;
if (control != null)
control.OnItemsSourceChanged((IEnumerable)e.OldValue, (IEnumerable)e.NewValue);
}
private void OnItemsSourceChanged(IEnumerable oldValue, IEnumerable newValue)
{
// Remove handler for oldValue.CollectionChanged
var oldValueINotifyCollectionChanged = oldValue as INotifyCollectionChanged;
if (null != oldValueINotifyCollectionChanged)
{
oldValueINotifyCollectionChanged.CollectionChanged -= new NotifyCollectionChangedEventHandler(newValueINotifyCollectionChanged_CollectionChanged);
}
// Add handler for newValue.CollectionChanged (if possible)
var newValueINotifyCollectionChanged = newValue as INotifyCollectionChanged;
if (null != newValueINotifyCollectionChanged)
{
newValueINotifyCollectionChanged.CollectionChanged += new NotifyCollectionChangedEventHandler(newValueINotifyCollectionChanged_CollectionChanged);
}
}
void newValueINotifyCollectionChanged_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
//Do your stuff here.
}
Use a DependencyProperty ItemsSource in your CustomControl and then bind to this DependencyProperty
This is the XAML-Code (Recognize the DataContext of the ListBox):
<UserControl
x:Name="MyControl">
<ListBox
DataContext="{Binding ElementName=MyControl}"
ItemsSource="{Binding ItemsSource}">
</ListBox>
</UserControl>
This is the CodeBehind:
public partial class MyCustomControl
{
public IEnumerable ItemsSource
{
get { return (IEnumerable)GetValue(ItemsSourceProperty); }
set { SetValue(ItemsSourceProperty, value); }
}
public static readonly DependencyProperty ItemsSourceProperty =
DependencyProperty.Register("ItemsSource", typeof(IEnumerable),
typeof(ToolboxElementView), new PropertyMetadata(null));
}
This is the Code, where you use your "MyCustomControl":
<Window>
<local:MyCustomControl
ItemsSource="{Binding MyItemsIWantToBind}">
</local:MyCustomControl>
</Window>
Simplified answer.
public IEnumerable ItemsSource
{
get => (IEnumerable)GetValue(ItemsSourceProperty);
set => SetValue(ItemsSourceProperty, value);
}
public static readonly DependencyProperty ItemsSourceProperty =
DependencyProperty.Register("ItemsSource", typeof(IEnumerable), typeof(UserControl1), new PropertyMetadata(null, (s, e) =>
{
if (s is UserControl1 uc)
{
if (e.OldValue is INotifyCollectionChanged oldValueINotifyCollectionChanged)
{
oldValueINotifyCollectionChanged.CollectionChanged -= uc.ItemsSource_CollectionChanged;
}
if (e.NewValue is INotifyCollectionChanged newValueINotifyCollectionChanged)
{
newValueINotifyCollectionChanged.CollectionChanged += uc.ItemsSource_CollectionChanged;
}
}
}));
private void ItemsSource_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
// Logic Here
}
// Do Not Forget To Remove Event On UserControl Unloaded
private void UserControl1_Unloaded(object sender, RoutedEventArgs e)
{
if (ItemsSource is INotifyCollectionChanged incc)
{
incc.CollectionChanged -= ItemsSource_CollectionChanged;
}
}
How do you implement a Silverlight 4 command to execute when the user control loads instead of being mapped to an explicit button click?
Or simply add a trigger in xaml for your UserControl:
<i:Interaction.Triggers>
<i:EventTrigger EventName="Loaded">
<si:InvokeDataCommand Command="{Binding MyCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
Create a DependencyProperty of type ICommand:-
#region public ICommand LoadedCommand
public ICommand LoadedCommand
{
get { return GetValue(LoadedCommandProperty) as ICommand; }
set { SetValue(LoadedCommandProperty, value); }
}
public static readonly DependencyProperty LoadedCommandProperty =
DependencyProperty.Register(
"LoadedCommand",
typeof(ICommand),
typeof(MainPage),
new PropertyMetadata(null));
#endregion public ICommand LoadedCommand
Also add a something to act as the command parameter:-
#region public object LoadedCommandParameter
public object LoadedCommandParameter
{
get { return GetValue(LoadedCommandParameterProperty) as object; }
set { SetValue(LoadedCommandParameterProperty, value); }
}
public static readonly DependencyProperty LoadedCommandParameterProperty =
DependencyProperty.Register(
"LoadedCommandParameter",
typeof(object),
typeof(MainPage),
new PropertyMetadata(null));
#endregion public object LoadedCommandParameter
Now set up its execution like this:-
public UserControl1()
{
InitializeComponent();
Loaded += UserControl1_Loaded;
}
void UserControl1_Loaded(object sender, RoutedEventArgs e)
{
if (LoadedCommand != null && LoadedCommand.CanExecute(LoadedCommandParameter))
{
LoadedCommand.Execute(LoadedCommandParameter);
}
}
Now if your ViewModel (has a command called StartStuff) then:-
<UserControl1 LoadedCommand="{Binding StartStuff}" .... >
Thats a load of code. The concise version without the code behind
public class LoadedBehaviour
{
public static ICommand GetLoadedCommand(DependencyObject dependencyObject)
{
return (ICommand)dependencyObject.GetValue(LoadedCommandProperty);
}
public static void SetLoadedCommand(DependencyObject dependencyObject, ICommand value)
{
dependencyObject.SetValue(LoadedCommandProperty, value);
}
public static Action GetLoadedCommandExecutor(DependencyObject dependencyObject)
{
return (Action)dependencyObject.GetValue(LoadedCommandExecutorProperty);
}
public static void SetLoadedCommandExecutor(DependencyObject dependencyObject, Action value)
{
dependencyObject.SetValue(LoadedCommandExecutorProperty, value);
}
public static readonly DependencyProperty LoadedCommandProperty = DependencyProperty.Register("LoadedCommand", typeof(ICommand), typeof(FrameworkElement), new PropertyMetadata(OnPropertyChanged));
public static readonly DependencyProperty LoadedCommandExecutorProperty = DependencyProperty.Register("LoadedCommandExecutor", typeof(Action), typeof(FrameworkElement), new PropertyMetadata(OnPropertyChanged));
private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (!(d is FrameworkElement))
{
throw new ArgumentException("Loaded command can only be used on FrameworkElements");
var executor = GetLoadedCommandExecutor(d);
if(executor == null)
{
executor = () =>
{
var command = GetLoadedCommand(d);
command.Execute(e);
};
SetLoadedCommandExecutor(d, executor);
((FrameworkElement)d).Loaded += (obj, args) => executor();
}
}
}