Send a CommanArgument with MouseLeftButtonUp - silverlight

I would like that my UIElement control acts like a LinkButton in ASP.Net when clicked, and sends an CommandArgument on MouseLeftButtonUp. I suppose I need to make a custom event for this, so I created a OnCommand event like this:
public delegate void OnCommand(object sender, CommandEventArgs e);
public class CommandEventArgs : EventArgs
{
public string CommandArgument { get; set; }
}
How can I add this event to MouseLeftButtonUp on my UIElement, and also pass the CommandArgument? Or is there another way to accomplish the effect of a LinkButton?

I didnt figure out a solution with custom events, so I made a UserControl instead, with a CommandArgument and CommandName properties.
public partial class LinkButton : UserControl
{
public string CommandArgument { get; set; }
public string CommandName { get; set; }
public LinkButton()
{
InitializeComponent();
CommandArgument = String.Empty;
CommandName = String.Empty;
}
public void AddElemnent(UIElement obj)
{
LayoutRoot.Children.Add(obj);
}
}

Related

Viewmodel Binding to CommandParameter that uses a Converter in WPF

I am trying to binding a number to a Enum located in the view model. I haven't been able to pass the value from the view to the viewmodel through the converter. Is this even possible? I haven't seen anything online that solves this and none of my attemps have worked either.
Viewmodel
public enum TimerOptions
{
FifteenMinutes,
OneHour,
Tomorrow
}
private ICommand _timerCommand;
public ICommand TimerCommand => _timerCommand ??
(_timerCommand = new RelayCommand<TimerOptions>(StartTimer));
private async void StartTimer(TimerOptions option){ .... }
View
<Button Command="{Binding TimerCommand}"
Tag="0"
CommandParameter="{Binding Path=Tag, Converter={StaticResource BidirectionalEnumConverter}}">15 minutes</Button>
In the above example, when the user clicks the button, I want my function to get the first enum value of FifteenMinutes as the parameter. I've tried this by adding a Tag (as seen), adding an x:Name to the Button and also playing around with Source and Path in the binding. Nothing has worked.
Is this possible? I've been trying to solve this for hours, I haven't found anything online.
I want my function to get the first enum value of FifteenMinutes as the parameter.
Why not just do the converter operation in the VM from the info passed in on a string in the command parameter?
Example
<Button Command="{Binding TimerCommand}"
Tag="1"
CommandParameter=1
Then have a ICommand based on that such as
public ICommand TimerCommand =>
new OperationCommand(async (oTag) => await StartTime(oTag).ConfigureAwait(true));
private bool IsOperation { get; set; }
private async void StartTimer(object oTag)
{
int tagId = (int)oTag;
//.... do the convert operations here...
...
// Access VM properties here
IsOperation = true;
await ....;
}
Here is the commanding structure I use instead of Relay.
public class OperationCommand : ICommand
{
#region Variables
private Func<object, bool> CanExecuteHandler { get; set; }
private Action<object> ExecuteActionHandler { get; set; }
public bool InSeparateThread { get; set; }
#endregion
#region Properties
#endregion
#region Construction/Initialization
public OperationCommand(Action<object> executeAction, bool inSeparateThread = false)
{
InSeparateThread = inSeparateThread;
ExecuteActionHandler = executeAction
?? throw new ArgumentNullException(nameof(executeAction));
}
public OperationCommand(Action<object> executeAction,
Func<object, bool> canExecute) : this(executeAction)
{
CanExecuteHandler = canExecute;
}
// Here to adhere to ICommand, change to below if needed
//public event EventHandler CanExecuteChanged;
event EventHandler ICommand.CanExecuteChanged
{
add {}
remove {}
}
#endregion
#region Methods
public bool CanExecute(object parameter) => CanExecuteHandler?.Invoke(parameter) ?? true;
// public void RaiseCanExecuteChanged() => CanExecuteChanged?.Invoke(this, new EventArgs());
public void Execute(object parameter)
{
ExecuteActionHandler?.Invoke(parameter);
}
#endregion
}
}

Binded property not refreshing while event called from another User Control

To simplify situation. I have MainWindow with two user controls, all of them have corresponding Viewmodels. Everything works fine, properties bind and so on, beside one functionality.
I want to refresh data on second user control after event happened in the first one. Unfortunetly in this scenario, PropertyChanged event (derived from INotifyPropertyChanged, defined in ViewModelBase) is null.
However, if I raise an event from second user control, property on view gets updated as expected!
public class MainWindowViewModel : ViewModelBase
{
public FirstUserControl FirstUserControl {get; set;}
public SecondUserControl SecondUserControl {get; set;}
public MainWindowViewModel ()
{
FirstUserControl =new FirstUserControl();
FirstUserControl.RaiseClicked+=OnRaiseClicked;
SecondUserControl = new SecondUserControl();
SecondUserControl .RaiseClicked+=OnRaiseClicked;
}
private void OnRaiseClicked(object sender, EventArgs e)
{
SecondUserControl.RefreshView();
}
}
public class FirstUserControl : ViewModelBase
{
public ICommand Raise { get; private set; }
public EventHandler RaiseClicked {get;set;}
public FirstUserControl ()
{
Raise = new RelayCommand( p=> RaiseClicked(this, null));
}
}
public class SecondUserControl: ViewModelBase
{
public ICommand Raise { get; private set; }
public EventHandler RaiseClicked {get;set;}
public string Title
{
get
{
return MyLogic.GetCurrentTitle(); // debuggers enter here only while event on second user control raised
}
}
public void RefreshView()
{
OnPropertyChanged("Title"); // debugger enter here in cases
}
}
I suppose there is something with threads going on, but I'm not that familiar with WPF to work out it by my own. Can someone help how to quickly and easy make event from first UC refresh data on the second?

command not binding properly

Please find the code used for simple binding.
Xaml code:
Button Command="{Binding BoldCommand}"
C# code:
public partial class MainWindow : RibbonWindow
{
public BoldCommand BoldCommand
{
get;
set;
}
public MainWindow()
{
InitializeComponent();
BoldCommand = new BoldCommand();
DataContext = BoldCommand;
}
}
public class BoldCommand : ICommand
{
public BoldCommand()
{
}
public bool CanExecute(object parameter)
{
return true;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
}
}
The problem is that your BoldCommand in your DataContext does not have a BoldCommand property.
The major problem you are going to have is that you have conjoined your View and ViewModel. Replace your MainWindow code with the following and it should work.
public partial class MainWindow : RibbonWindow
{
public MainWindow()
{
InitializeComponent();
DataContext = new MainViewModel();
}
}
public class MainViewModel
{
public MainViewModel()
{
BoldCommand = new BoldCommand();
}
public BoldCommand BoldCommand { get; set; }
}

Why is my Silverlight usercontrol property null?

I have a usercontrol:
<Grid x:Name="LayoutRoot" Background="White">
<TextBlock Name="TextBlock1" Text="Text for"></TextBlock>
</Grid>
It has a cs file:
public partial class MyUserControl: UserControl
{
public string MyProperty { get; set; }
public MyUserControl()
{
InitializeComponent();
DoSomething();
}
private void DoSomething()
{
TextBlock1.Text = TextBlock1.Text + MyProperty;
}
}
I'm trying to add this usercontrol programatically to another user control:
UserControls.MyUserControl myUserControl = new UserControls.MyUserControl();
myUserControl.MyProperty = "Something";
MyStackPanel.Children.Add(myUserControl);
I thought I've done something like this before without any issues, but in this case MyProperty is always null. What did I do wrong?
Your code is fine as-is except for when you are calling DoSomething(). You should avoid GUI interaction in the constructor of a control for many reasons (not the least of which is that your property is not yet set as pointed out by Mark Hall). I do not however recommend adding different constructors just to take initial properties.
You simply want to defer that call to the Loaded event of the control.
Assuming you set the event in the Xaml like this:
<navigation:Page x:Class="MyUserControl"
...
Loaded="Page_Loaded">
Your code would look like:
public partial class MyUserControl: UserControl
{
public string MyProperty { get; set; }
public MyUserControl()
{
InitializeComponent();
}
private void Page_Loaded(object sender, RoutedEventArgs e)
{
DoSomething();
}
private void DoSomething()
{
TextBlock1.Text = TextBlock1.Text + MyProperty;
}
}
If you want to set the Loaded event in code it would just look like:
public partial class MyUserControl: UserControl
{
public string MyProperty { get; set; }
public MyUserControl()
{
InitializeComponent();
Loaded += Page_Loaded;
}
private void Page_Loaded(object sender, RoutedEventArgs e)
{
DoSomething();
}
private void DoSomething()
{
TextBlock1.Text = TextBlock1.Text + MyProperty;
}
}
The it is just down to you setting all your desired properties after construction, but before the page is loaded as you are doing already.
UserControls.MyUserControl myUserControl = new UserControls.MyUserControl();
myUserControl.MyProperty = "Something";
MyStackPanel.Children.Add(myUserControl); // This makes it visible when Loaded event is called
What is happening is that you are calling DoSomething in your contructor before you have set MyProperty so MyProperty is equal to null. If you want the data to be there when the UserControl is created you can set it in the Constructor.
i.e.
public partial class MyUserControl : UserControl
{
public string MyProperty { get; set; }
public MyUserControl() //Default Constructor
{
InitializeComponent();
}
public MyUserControl(string MyData)
{
InitializeComponent();
MyProperty = MyData;
DoSomething();
}
private void DoSomething()
{
TextBlock1.Text = TextBlock1.Text + MyProperty;
}
}
and create it like this.
MyUserControl myUserControl = new MyUserControl(" Something");
MyStackPanel.Children.Add(myUserControl);

Silverlight Wcf Ria service viewmodel combobox

Ok I'll make this very simple! Here are viewmodels :
public class ObjectsModel
{
public event PropertyChangedEventHandler PropertyChanged = delegate { };
private string _objectName;
public string ObjectName
{
get
{
return _objectName;
}
set
{
if (value != _objectName)
{
_objectName = value;
PropertyChanged(this, new PropertyChangedEventArgs("ObjectName"));
}
}
}
public IEnumerable<Object> Objects {get;set;}
public ICommand AddCommand { get; private set; }
public ICommand SaveChangesCommand { get; private set; }
myDomainContext context = new myDomainContext();
public ObjectsModel()
{
objects = context.Objects;
context.Load(context.GetObjectsQuery());
}
}
public class InventoryModel
{
public event PropertyChangedEventHandler PropertyChanged = delegate { };
public IEnumerable<Inventory> Inventories {get;set;}
public ICommand AddCommand { get; private set; }
public ICommand SaveChangesCommand { get; private set; }
myDomainContext context = new myDomainContext();
public ObjectsModel()
{
objects = context.Objects;
context.Load(context.GetObjectsQuery());
}
}
So what I'm trying to do is in my second form where I want to add an inventory for an object, I have to select the object in a combobox. The question is, how do I fill my combobox? Create another instance of the "ObjectsModel" in the InventoryModel? or use another "context" where I would query the other table? Or is there an easier Xaml approach? If I'm not clear, tell me I'll put more examples/code.
tx a lot!
You want to bind the contents of the combobox to a list of items provided by your ViewModel and bind the selected item to another property on the same ViewModel.
Please get into the habit of naming actual view models to end in "ViewModel", rather than "Model", so they do not clash with your other "real" models. It actually looks like you are binding directly to your business models instead of ViewModels (which is not good).

Resources