<Button x:Name="ButtonLogin"
StyleId="ButtonLogin"
Grid.Row="5"
BackgroundColor="#F44336"
BorderRadius="0"
TextColor="White"
Text="Login to Meetup"
Command="{Binding LoginCommand}" />
or
<Button x:Name="ButtonLogin"
StyleId="ButtonLogin"
Grid.Row="5"
BackgroundColor="#F44336"
BorderRadius="0"
TextColor="White"
Text="Login to Meetup"
Clicked="LogMeIn" />
Does the use of one or the other matter specifically when designing a Xamarin app?
Which approach should be used?
Regardless of whether it is WPF XAML, Silverlight XAML or Xamarin XAML, the choice to use one or the other does not affect the end performance of the app for at some point it all gets distilled down to codebehind and ultimately into machine code.
With that said if one uses commanding it can be designed to work within the MVVM paradigm and give direct access to functionality which can be either based on the View, ViewModel and even the Model depending on how it is set up.
Since a command is based on ICommand interface, that gives the XAML more flexibility to either allow or disallow operations due to the CanExecute functionality which is a big selling point if used.
Both can be used in Xamarin xaml template[?]
The click event is local to the control and cannot be used in a template. The click event can work with MVVM but it should not be called from anywhere outside the View that contains it.
My advice is to use Commanding where re-use particulary amongst Pages/Views is prevalent and also if there exists a need to either directly or indirectly affect styles and visibility; use it. Otherwise if the operation is just local to the page/control there is no reason not to use code-behind.
Related
Scenario: Developing a "thick" client in UWP, using c# destined for the desktop of Windows 8.1/10 (a store app).
In my user interface, I tried to use the following inline
<StackPanel Grid.Column="0">
<TextBlock x:Name="Qty_Size_Crust" Margin="25,10,20,0" Padding="0,0,0,0" TextAlignment="Left" TextWrapping="Wrap" MaxHeight="25" Foreground="#ff230909" FontFamily="Segoe UI" FontSize="16" xml:space="preserve" HorizontalAlignment="Left">
if ({Binding WidgetName} == "Backend")
{
<Run Text="{Binding ItemCode, Converter=ItemCodeToDescriptionConverter}"/>
}
else
{
<Run Text="See Administrator}"/>
}
</TextBlock>
The compiler would accept this, but during execution, I would neither see Item Description nor See Administrator. Is there something else I should be doing in order for this work? I was able to work around this by putting the code in the ViewModel, but wondered why this didn't work (or maybe it shouldn't).
XAML doesn't work with inline scripts so the answer is simply - it's not supported.
In your example - the condition code is simply added as text runs in the TextBlock, so the compiler accepts that.
As for the best solution to your specific problem - a condition in the view model is a good one. A TemplateSelector would work on the view side, but requires more code. View model might actually also be the best place to put it if you want to be able to test it, so it really is the right way to do it. Putting logic in the view layer would simply add code that can't be unit-tested.
In WPF, I can add whatever UI into ListBoxItems by providing the ListBox with an ItemTemplate:
<ListBox ItemsSource="{Binding}">
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderThickness="1" BorderBrush="Gray" CornerRadius="8" Padding="4,0,4,0">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<CheckBox Grid.Column="1" Content="Is Active Customer" IsChecked="{Binding IsActive}"/>
<Label Content="Id:" Grid.Row="1" HorizontalAlignment="Right"/>
<Label Content="Name:" Grid.Row="2" HorizontalAlignment="Right"/>
<TextBox Text="{Binding Id}" Grid.Row="1" Grid.Column="1"/>
<TextBox Text="{Binding Name}" Grid.Row="2" Grid.Column="1"/>
</Grid>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Results in:
Is there any way to achieve the same in Windows Forms?
Edit:
1 - Is there any way to achieve the same in Windows Forms, all while maintaining separation of concerns between the View and the Application Logic in such a way that if I later wanted to completely redefine the View, I wouldn't have to refactor the entire application?
2 - Does winforms support databinding in such a way that each of my ListBoxItems can be bound to a complex Entity, eventually including an intermediate type conversion from Model data to UI data and back, in such a way that I don't have to write tons of boilerplate code to populate the view and then pass the UI values back into the Model in order to save?
3 - What if I wanted to introduce Animations in such a way that the currently SelectedItem would animatedly expand itself into some kind of "Row Details" mode, where you can see a lot of additional information?
4 - Does winforms support UI Virtualization in such a way that if I have, say 1 million items it doesn't take a lifetime to load the UI, and only render what's visible on screen?
5 - Say I wanted to introduce complex graphics to the equation. Is winforms rendering hardware-accelerated?
6 - How do I make all this Resolution Independent in such a way that the ListBox and all its contents stretch to the available window size in order to leverage larger screens while maintaining compatibility with smaller ones?
7 - It's been suggested to use the ListView control instead of a regular ListBox, does the ListView provide the ability to add ANY UI into it? can I add Videos for example for each item? or a complex Master/Detail template with Save and edit Buttons?
8 - Does winforms provide a consistent and adequate Document Model that enables the creation of high-fidelity WYSIWYG documents and other types of rich content?
To answer the overarching question - how to do this in WinForms - I'd suggest the following:
Use a WPF ListBox in your WinForms application, wrapped in an ElementHost. This has its own issues, but I think it's the cleanest way to get the desired effect.
if that doesn't fit the bill, then
Use a third party control suite that has components which support this (Infragistics and DevExpress both do).
Spin your own derived ListBox control that overrides paint, etc to render the desired content.
To your individual questions:
Is there any way to achieve the same in Windows Forms, all while maintaining separation of concerns between the View and the Application Logic in such a way that if I later wanted to completely redefine the View, I wouldn't have to refactor the entire application?
In the past, I've used the MVP (model-view-presenter) paradigm with Windows Forms. It works for separating the view from the business logic, albeit not as cleanly as an MVVM approach with WPF. The best advice I can give is: don't put business logic in event handlers.
Does winforms support databinding in such a way that each of my ListBoxItems can be bound to a complex Entity, eventually including an intermediate type conversion from Model data to UI data and back, in such a way that I don't have to write tons of boilerplate code to populate the view and then pass the UI values back into the Model in order to save?
No. Windows Forms databinding does not support complex data binding. You could implement something yourself via ICustomTypeDescriptor or IBindingSource that can take complex paths and evaluate them for binding purposes...but nothing exists out of the box for this.
What if I wanted to introduce Animations in such a way that the currently SelectedItem would animatedly expand itself into some kind of "Row Details" mode, where you can see a lot of additional information?
You'd have to roll your own Windows Forms ListBox and ListBoxItems and override the paint operations.
Does winforms support UI Virtualization in such a way that if I have, say 1 million items it doesn't take a lifetime to load the UI, and only render what's visible on screen?
Not out of the box, but some third party control suites have components that support types of virtualization...but not at all in the same way WPF does.
Say I wanted to introduce complex graphics to the equation. Is winforms rendering hardware-accelerated?
Windows Forms is based on GDI+. GDI+ is not hardware accelerated: Windows Forms very slow under Windows7?
How do I make all this Resolution Independent in such a way that the ListBox and all its contents stretch to the available window size in order to leverage larger screens while maintaining compatibility with smaller ones?
You can use Docking and Anchoring in Windows Forms to accomplish this. Or you can add custom event handlers to perform appropriate layout adjustments based on resolution and Window size.
It's been suggested to use the ListView control instead of a regular ListBox, does the ListView provide the ability to add ANY UI into it? can I add Videos for example for each item? or a complex Master/Detail template with Save and edit Buttons?
This is simplifying...but a ListView is simply a ListBox that supports multiple view types. It is also more limited in terms of databinding. http://blog.gfader.com/2008/09/winforms-listbox-vs-listview.html.
Does winforms provide a consistent and adequate [Document Model][2] that enables the creation of high-fidelity WYSIWYG documents and other types of rich content?
No. Not at all. Not even a little bit.
In short, if it's an acceptable solution, I'd wrap your WPF ListView in an ElementHost and call it a day.
We did this by using UserControls in a scrollable panel.
Prepared a user control which has all the editing control on it.
Add them to a scrollable panel with dosk property is set to Top.
Implemented the item selection behaviour by watching the focus and click events on the added user control items.
I am currently writing a Windows 8 application. I am trying to call a method in my ViewModel. I want this method to be called when an item is double clicked. I have defined the following DataTemplate in my XAML to do this:
<DataTemplate x:Key="ItemTemplate">
<StackPanel Orientation="Horizontal">
<Image Width="185" Height="185" Stretch="Fill" Source="{Binding Path=Image}" DoubleTapped="{Binding Path=MethodIWishToBindTo}" IsDoubleTapEnabled="True" />
</StackPanel>
</DataTemplate>
The problem, of course, is the error message for my binding to MethodIWishToBindTo:
Invalid value for 'DoubleTapped'. Event values must be text
What is the best way for me to get around this ? I could call the method in the code-behind, however the method uses a property in my ViewModel, "SelectedItemInList", which I don't believe can be accessed from the code behind.
Can anyone offer me some advice for this problem ?
Thanks a lot.
You could use Interactivity and a custom behavior to trigger the event. Here's a post that topically covers an example:
MVVM-Light EventToCommand Behavior for CheckBox Checked/Unchecked in Silverlight
MVVM-Light definitely makes this easier, but it's possible without as well.
Here's an example of without: http://blog.roboblob.com/2010/01/26/binding-ui-events-from-view-to-commands-in-viewmodel-in-silverlight-4/
I am trying to learn the MVVM pattern (C#), having come from a Windows Forms background. I am using the MVVM Light toolkit, and so far I think it is brilliant.
I have made several small applications, however one thing I am struggling with is introducing a second view.
I want to (for example), have a button on my MainViewModel, which via a RelayCommand, opens up a new Window - let's say an "About" window. I have done hours of research on the web for this however it seems I can't get my AboutViewModel to communicate with/show my AboutView.
I have placed a receiving messenger in the code-behind constructor of the AboutView.xaml - however I can't get it to receive any messages from the AboutViewModel, and thus can't make it 'Show()'.
If anyone has an example of an Mvvm Light WPF app using multiple views that would be great :)
There are two ways I can think to do this easily
The first would be to use a Popup instead of a new Window. For example, I often put properties in my ViewModel for PopupContent and IsPopupVisible, and set those values anytime I want to display my Popup control. For example, a ShowAboutPopup relay command might run something like this:
void ShowAboutPopup()
{
PopupContent = new AboutViewModel();
IsPopupVisible = true;
}
You can display it using a Popup object, or a custom UserControl. I prefer to use my own custom Popup UserControl, which will usually end up looking like this:
<Window>
<Canvas x:Name="RootPanel">
<SomePanel>
<!-- Regular content goes here -->
</SomePanel>
<local:PopupPanel Content="{Binding PopupContent}"
local:PopupPanel.IsPopupVisible="{Binding IsPopupVisible}"
local:PopupPanel.PopupParent="{Binding ElementName=RootPanel}" />
</Canvas>
</Window>
The PopupContent property is a ViewModel (such as an AboutViewModel), and DataTemplates are used to tell WPF to draw specific ViewModels with specific Views
<Window.Resources>
<DataTemplate DataType="{x:Type local:AboutViewModel}">
<local:AboutView />
</DataTemplate>
</Window.Resources>
The other method is to have some kind of ApplicationViewModel that runs on startup, and is responsible for the overall application state, which includes which window(s) are open.
Typically I prefer to have a single ApplicationView that contains a ContentControl to display the current page
<Window>
<ContentControl Content="{Binding CurrentViewModel}" />
</Window>
however it can also be used to manage multiple windows. If you do use it to manage multiple Window objects, be warned that this will not be a pure ViewModel because it will need to access some View-specific objects, and referencing UI objects it not something a ViewModel should do. For example, it may subscribe to receive ShowWindow messages, and upon receiving those messages it would create the specified View and show it, and possibly hide the current window as well.
Personally, I try to avoid multiple windows as much as possible. My usual method is to have a single View that contains consistent application objects for any page, and a ContentControl containing dynamic content that changes. I have an example using this navigation style on my blog if you're interested
As i can see you want a navigation in your MVVM app?
Word goes to the creator of MVVM Light - Laurent Bugnion - with his post about using Navigation Service for switching Views. It's actually about Windows Phone & Silverlight but same should apply to WPF.
Also this answer in related question uses this approach.
I'm facing some problems binding a CommandParameter to its own Command in an application built using Prism 2.2 as MVVM . Let me introduce what it's happening.
I've got a customized listbox with a property named NumPageElements, and a couple of buttons to scroll through the list who needs that property. A simplified xaml of what I need (and works) in wpf is:
<Button x:Name="PageDownButton" Command="{Binding PageDownCommand}" CommandParameter="{Binding ElementName=ItemsListBox, Path=NumPageElements}" />
<Custom:MyOwnListBox x:Name="ItemsListBox" x:NumPageElements="{Binding ElementsPerPage, Mode=OneWayToSource}" >
. . .
</Custom:MyOwnListBox>
To have the same behaviour in Silverlight I wrote this xaml:
<Button Name="PageDownButton" Command="{Binding PageDownCommand}" CommandParameter="{Binding ElementName=ItemsListBox, Path=NumPageElements}" />
<Custom:MyOwnListBox Name="ItemsListBox" NumPageElements="{Binding Path=ElementsPerPage, Mode=TwoWay, UpdateSourceTrigger=Explicit}" >
. . .
</Custom:MyOwnListBox>
PageDownButton is an IApplicationCommand, ElementsPerPage is a property exposed by the presenter.
Now, the first time I open this view the buttons made in that way look enabled but they aren't 'clickable'. If I switch to a different view and I go back to the view with those button, they finally catch the correct behavior. It looks like it doesn't initialize correctly the first time the condition of the command (infact they should be disabled until I insert an item in the listbox), as if the parameter given via the CommandParameter property isn't initiliazed correctly. But I can't understand why switching between the views make it works.
I suspected I should force the UpdateSource of the bindings (I did it for ItemsListBox.NumPageElements and for PageDownButton.CommandParameter) after the view has been loaded, but doing it in the code behind was not of any help.
What I am doing wrong?
Thanks for any reply,
Mat.