How to do binding based on a condition in .net maui? - mvvm

I'd like to ask how to do the conditional binding in a .net Maui app. for example
if I have a class
public class ClassA
{
public string Property1{get;set;}
public string Property2{get;set;}
}
and I don't have access to the class implementation so I cannot add methods
and in my view, I want to bind to Property1 if some condition is true and bind to Property2 if that condition was false.
Is there a way to do conditional binding from the view itself without changing ClassA implementation?

I think you could achieve this goal by setting binding property in code-behind (xaml.cs file) instead of .xaml file.
For example:
In MainPage.xaml, you have a label with name labelA:
<Label x:Name="labelA" />
In MainPage.xaml.cs constructor, you could bind Text property of labelA to one of viewModel properties based on a condition.
public MainPage(ClassA viewModel)
{
InitializeComponent();
BindingContext = viewModel;
if (true condition)
{
labelA.SetBinding(Label.TextProperty, nameof(viewModel.Property1));
}
else
{
labelA.SetBinding(Label.TextProperty, nameof(viewModel.Property2));
}
}

Related

Spring form path with multiple model attributes with the same property name

The problem is that I have a spring form and 2 #ModelAttribute params with the same properties in my controller. The 'commandName' parameter of the the form is set to one of my modelAttributes names. I was surprised that the maps the property not only to the model attribute specified with 'commandName', but also to the second one.
I haven't found the exact solution here, except the similar to mine: Spring-form multiple forms with same model atribute name properties
But in my case I can't see any 'strange things', I have one form, one Model attribute to bind this form, and one model attribute to have accsess to controller scoped #SessionAttribute.
I've also tried to use form's 'modelAttribute' parameter (Actually I can't see any difference between them), but it didn't help.
My code example:
view.jsp:
<form:form name="form" action="/myAction" method="POST" commandName="model1">
<form:input path="property"/>
....
<input type="submit" value="Submit"/>
</form:form>
Controller.java
#SessionAttributes("model2")
class Controller {
#RequestMapping(value = "/myAction", method = POST)
public String submitEditSite(final #ModelAttribute(value = "model1") Model1 model1,
final #ModelAttribute(value = "model2") Model2 model2) {
....
return "redirect:/home";
}
}
Model1.java Model2.java
class Model1 {
private String property;
}
class Model2 {
private String property;
}
Where am I wrong?
If I understand you correctly you want to prevent the setting of any property on model2, right?
Then this should do:
#InitBinder("model2")
public void initBinder(WebDataBinder binder) {
binder.setDisallowedFields("*");
}

Pass parameter from Winform to UserControl

I have a UserControl in a Winform and I would like to pass a parameter, here's what I'm doing:
In the User Control:
public List<ushort[]> pixels16 { get; set;}
In the Form:
VolumeView controlv = new VolumeView(); //VolumeView is the UserControl
controlv.pixels16 = pixels16_img; //pixels16 is the variable in the Form that I need to use in the UserControl
It works, however, when I run a function in the UserControl, then the value is set to null:
public void CreateVolume()
{
pixels16 is null!
}
what I'm doing wrong? I basically need to use a Form variable in a function within the UserControl..
Thanks!
Have you tried passing the object as a parameter in the UserControl's constructor?

WPF, C# and MVVM Exposing commands

Hi all I'm trying to get to grips with using MVVM, but I'm having a hard time :(, firstly for my question, I'm using the code provide in this MVVM article as a template for my learning.
My question is simple how do expose independent commands, in this case he has create a list of hyperlinks, but how do i create a single button that's fixed and does the same as the 'create new customer' link.
I created something like this(was added to the MainWindowViewModel.cs):
public CommandViewModel exposedCommand
{
get
{
return new CommandViewModel(
Strings.MainWindowViewModel_Command_CreateNewCustomer,
new RelayCommand(param => this.CreateNewCustomer())
);
}
}
and then in the xaml document i created a new button, this was added to the MainWindow.xaml
<Button
Content="Button"
Height="23"
HorizontalAlignment="Left"
Margin="6,303,0,0" Name="button1" VerticalAlignment="Top" Width="150"
Command="{Binding Path=exposedCommand}"
/>
I am not to sure if I'm missing something, or what I am where going wrong,
Soz if I sounding a bit naive I have only just started using MVVM and routed commands and so.
Oh another thing it does load the link it just doesn't create the tab, in other words if you would to add
Console.Writeline("HERE");
to the exposedCommand method
It would print out 'HERE' it just won't do anything when you click the button.
Thanks Any Help would be so appreciated.
Your XAML code is correct.
I also started off with Josh Smith's MVVM article.
Below is a stripped down example of how I implement Commands in my ViewModels:
public class ProjectViewModel : ViewModelBase
{
// Private variable for holding save command
private RelayCommand _saveCommand;
// Other fields here
// Constructors and properties and stuff here
// Command Property for Save button. Bind XAML to "SaveCommand"
public ICommand SaveCommand
{
get
{
if (_saveCommand == null) // Init command on first get
_saveCommand = new RelayCommand(param => this.SaveChanges(), param => this.CanSave);
return _saveCommand;
}
}
/// <summary>
/// Method called when save command is executed
/// </summary>
private void SaveChanges()
{
// Save logic here...
}
/// <summary>
/// Predicate for determining if SaveCommand is enabled
/// </summary>
private bool CanSave
{
get
{
return true; // Replace with SaveCommand predicate logic
}
}
}
If it still does not work, check you runtime output for BindingErrors. If there is a BindingError that implies that the View cannot find the SaveCommand, then your ViewModel is not correctly set to be the DataContext of the View. Let me know in the comments if this is the problem.
You can bind command to only those objects that has an implementation of ICommand interface.
In your example you are binding with view model object.
Instead of this create a property in view model that is a type of RelayCommand and bind this with button.
It should work.
The first thing that concerns me is your the code inside the getter of you property. You're returning a new object EVERY TIME the exposedCommand is accessed. That's not really recommended, you should store that in a backing property like so:
CommandViewModel _exposedCommand;
public CommandViewModel exposedCommand
{
get
{
if (_exposedCommand == null)
{
_exposedCommand = new CommandViewModel(
Strings.MainWindowViewModel_Command_CreateNewCustomer,
new RelayCommand(param => this.CreateNewCustomer()));
}
return _exposedCommand;
}
}
That being said the typical way to present your desired ICommand property is something like this:
RelayCommand _exposedCommand;
public ICommand exposedCommand
{
get
{
if (_exposedCommand == null)
_exposedCommand= new RelayCommand(param => this.CreateNewCustomer());
return _exposedCommand;
}
}

Getting custom type from TempData asp.net mvc 2

I have a custom class MyCustomType. In that class I have a property MyCustomProperty of type bool and another property MyCustomProperty1 of type bool also.
I need to check if MyCustomProperty is true in my View. I`m doing the following thing:
<%if ( TempData[ViewDataConstants.MyCustomTypeKey] != null && ((MyCustomType)TempData[ViewDataConstants.MyCustomTypeKey]).MyCustomProperty %>show some custom content.
But for some reason when Im running it I see error message that MyCustomTYpe could not be found are you missing an assembly reference bla-bla-bla. MyCustomType is in my controller its public and to check I even added a reference to the view. But it keep saying that there`s no MyCustomType class. What am I doing wrong?
Interesting, for some reason when I moved it to Common from Controllers namespace it suddenly worked. Still dont see why its not working while in Controllers namespace.
Both namespaces were included explicitly in the view.
No idea why it didn't work but quite honestly having all this code in a view looks wrong to me. Maybe it's just like me, Visual Studio doesn't like writing C# code in a view :-).
This should be a property on your view model:
public class MyViewModel
{
public bool MyCustomProperty { get; set; }
}
and inside your controller:
public ActionResult Foo()
{
var model = TempData[ViewDataConstants.MyCustomTypeKey] as MyCustomType ?? new MyCustomType();
var viewModel = Mapper.Map<MyCustomType, MyViewModel>(model);
return View(viewModel);
}
and finally inside your view:
<% if (Model.MyCustomProperty) { %>
show some custom content.
<% } %>
Now you no longer need any usings, castings, ... in the view.

how to parametrize an import in a View?

I am looking for some help and I hope that some good soul out there will be able to give me a hint :)
I am building a new application by using MVVM Light. In this application, when a View is created, it instantiates the corresponding ViewModel by using the MEF import.
Here is some code:
public partial class ContractEditorView : Window
{
public ContractEditorView ()
{
InitializeComponent();
CompositionInitializer.SatisfyImports(this);
}
[Import(ViewModelTypes.ContractEditorViewModel)]
public object ViewModel
{
set
{
DataContext = value;
}
}
}
And here is the export for the ViewModel:
[PartCreationPolicy(CreationPolicy.NonShared)]
[Export(ViewModelTypes.ContractEditorViewModel)]
public class ContractEditorViewModel: ViewModelBase
{
public ContractEditorViewModel()
{
_contract = new Models.Contract();
}
}
Now, this works if I want to open a new window in order to create a new contract... or in other words, it is perfect if I don't need to pass the ID of an existing contract.
However let's suppose I want to use the same View in order to edit an existing contract. In this case I would add a new constructor to the same View, which accepts either a model ID or a model object.
"Unfortunately" the ViewModel is created always in the same way:
[Import(ViewModelTypes.ContractEditorViewModel)]
public object ViewModel
{
set
{
DataContext = value;
}
}
As far as I know, this invokes the standard/no-parameters constructor of the corresponding ViewModel at composition-time.
So what I would like to know is how to differentiate this behavior? How can I call a specific constructor during composition time? Or how can I pass some parameters during the Import?
I really apologize if this question sounds silly, but I have only recently started to use MEF!
Thanks in advance,
Cheers,
Gianluca.
You CAN do this. Check out the Messenger implementation in MVVM-Light. You can pass a NotificationMessage(Of Integer) to send the right ID to the view model. The view model has to register for that type of message, and load it when a message is sent.
MEF Imports by default only have a parameterless constructor.