CaliburnMicro + RowDetailsTemplate: Details-View disappears - c#

I have a GridView which lists all my Products. The first column is a "GridViewToggleRowDetailsColumn" which expands a Details-View when clicked.
I use CaliburnMicro to load the Details-View like so:
<telerik:RadGridView ItemsSource="{Binding Products.View}"
SelectedItem="{Binding SelectedProduct,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
AutoGenerateColumns="False"
EnableRowVirtualization="False"
ShowGroupPanel="False"
RowDetailsVisibilityMode="Collapsed"
RowIndicatorVisibility="Collapsed"
cal:Message.Attach="[Event RowDetailsVisibilityChanged] =
[Action OnRowDetailsVisibilityChanged($eventArgs)]">
<telerik:RadGridView.RowDetailsTemplate>
<DataTemplate>
<ContentControl cal:View.Model="{Binding DataContext.ProductDetailsViewModel, RelativeSource={RelativeSource FindAncestor, AncestorType=telerik:RadGridView}}" />
</DataTemplate>
</telerik:RadGridView.RowDetailsTemplate>
<telerik:GridViewToggleRowDetailsColumn />
...Columndefinitions...
</telerik:RadGridView>
I can open and close the details as long as I stay on the same product. The problem occurs if I open the details while another details is already visible. Then the details of the first disappears and never comes back. See the screenshot:
The grey box is a placeholder for the details. I opened the details of the first 8 items one after another, but only the last one is showing. My guess is that Caliburn Micro can not locate the View anymore, but I have no idea why? Because I only have one ProductDetailsViewModel?
Also: in debug mode i noticed that the "ProductDetailsViewModel"-getter is accessed only once per item after expanding the row. Collapsing and expanding the same row does not access the getter again.
UPDATE:
Another approach, same effect: I say my ItemsSource is a collection of ProductDetailsViewModel and inherit my MainViewModel from Conductor<ProductDetailsViewModel>.Collection.OneActive, make the Grid binding with
ItemsSource = "{Binding Items}"
and in the xaml
<ContentControl cal:View.Model="{Binding DataContext.ActiveItem, RelativeSource={RelativeSource FindAncestor, AncestorType=telerik:RadGridView}}" />
in the SelectionChanged I do
ActivateItem(e.Row.Item as ProductDetailsViewModel);
Same as before, the ProductDetailsView is displayed for the current item, but disappears once I show the details of another product.

The problem was the view-caching of "IViewAware", which is automatically implemented by screens. Overwriting the "GetView" in the ProductDetailsViewModel solved the issue.
Related: Screens shared in multiple screens disappear after deactivation in Caliburn.Micro

Related

Binding fails without error

I have a CustomListView that has controls like TextBoxes, HyperLinks and Buttons.
I can't share the exact Code, but please bear with me.
I have a list, say of type person with attributes like personHeight, personWidth, etc.
The binding to the list is done at the list level.
The issue is, that all values are fetched from the database, but only one is populated, the remaining are blank.
Also I didn't get any binding error in the Output Window. What could be the issue?
The general syntax of the XAML (where personHeight is one of the properties of the list object):
<CustomGridViewColumn SortOnProperty="personHeight">
<CustomGridViewColumn.SortableHeader>
<TextBlock Text="Person Height" />
</CustomGridViewColumn.SortableHeader>
<CustomGridViewColumn.CellTemplate>
<DataTemplate>
<TextBox x:Name="personHeightText" Text="{Binding personHeight}" />
</DataTemplate>
</CustomGridViewColumn.CellTemplate>
<CustomGridViewColumn>
The binding is done as follows:
<CustomListView ItemsSource="{Binding Path=Persons}"
ItemContainerStyle="{StaticResource MyExpandableListViewItemStyle}"
ExpandedDataTemplate="{StaticResource ExpandedDataTemplate}"
ScrollViewer.CanContentScroll="False"
x:Name="GridList">

How to UWP Print ListView ItemTemplate

I'm trying to figure out how to print a ListView ItemTemplate using the uwp PrintHelper.cs sample. Everything works, except the print preview does not display items added to the ListView at runtime. I can add other controls such as a textbox, and the print preview will show it, so there must be something peculiar with printing databound ListView items at runtime, but I cannot find any information about it.
<ListView x:Name="ClipboardList"
xmlns:m="using:QuickieEdit.Models"
ItemsSource="{x:Bind ViewModel.MemoryItems}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="m:MemoryItem">
<StackPanel Orientation="Horizontal">
<Button x:Name="MemoryCopyBtn"
Content="Copy"
Click="How to Copy currently selected
MemoryListItem.Text?"/>
<TextBox x:Name="MemoryListItem"
Text="{x:Bind Memory, Mode=TwoWay}">
</TextBox>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
I cannot understand your exact query, but I think you may be facing situation where your ListView does not get updated with the model and hence does not show up while printing. You can use
ObservableCollection<Model> instead of List<Model>
This will solve your problem or if it does not please provide the c# code in detail as well
Cheers

Bind button in DataTemplate to command in the form's ViewModel

My problem is similar to the one described in this question:
WPF MVVM Button Control Binding in DataTemplate
Here is my XAML:
<Window x:Class="MissileSharp.Launcher.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MissileSharp Launcher" Height="350" Width="525">
<Grid>
<!-- when I put the button here (outside the list), the binding works -->
<!--<Button Content="test" Command="{Binding Path=FireCommand}" />-->
<ListBox ItemsSource="{Binding CommandSets}">
<ListBox.ItemTemplate>
<DataTemplate>
<!-- I need the button here (inside the list), and here the binding does NOT work -->
<Button Content="{Binding}" Command="{Binding Path=FireCommand}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Window>
It's just a ListBox, bound to an ObservableCollection<string> named CommandSets (which is in the ViewModel).
This binding works (it displays a button for each item in the collection).
Now I want to bind the button to a command (FireCommand), which is also in the ViewModel.
Here's the relevant part of the ViewModel:
public class MainWindowViewModel : INotifyPropertyChanged
{
public ICommand FireCommand { get; set; }
public ObservableCollection<string> CommandSets { get; set; }
public MainWindowViewModel()
{
this.FireCommand = new RelayCommand(new Action<object>(this.FireMissile));
}
private void FireMissile(Object obj)
{
System.Windows.MessageBox.Show("fire");
}
}
The binding of this button does NOT work.
From what I've understood from the question I linked above, the binding doesn't work because:
(correct me if I'm wrong)
The button is inside the ListBox, so it only "knows" the binding of the ListBox (the ObservableCollection, in this case), but not the binding of the main window
I'm trying to bind to a command in the main ViewModel of the main window (which the button doesn't "know")
The command itself is definitely correct, because when I put the button outside the ListBox (see the XAML above for an example), the binding works and the command is executed.
Apparently, I "just" need to tell the button to bind to the main ViewModel of the form.
But I'm not able to figure out the right XAML syntax.
I tried several approaches that I found after some googling, but none of them worked for me:
<Button Content="{Binding}" Command="{Binding RelativeSource={RelativeSource Window}, Path=DataContext.FireCommand}" />
<Button Content="{Binding}" Command="{Binding Path=FireCommand, Source={StaticResource MainWindow}}" />
<Button Content="{Binding}" Command="{Binding Path=FireCommand, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" />
Could someone please:
give me the proper XAML to bind the button inside the ListBox to a command in the form's MainViewModel?
point me to a link where this advanced binding stuff is explained in a way that a WPF/MVVM beginner can understand?
I'm feeling like I'm just copying and pasting arcane XAML incantations, and so far I don't have any clue (and can't find any good documentation) how I would figure out by myself in which cases I'd need RelativeSource or StaticResource or whatever instead of a "normal" binding.
It's:
{Binding DataContext.FireCommand,
RelativeSource={RelativeSource AncestorType=ListBox}}
No need to walk up to the root unless you actually change the DataContext along the way, but as the ListBox seems to bind to a property on the main VM this should be enough.
The only thing i recommend reading is the Data Binding Overview, and the Binding class documentation (including its properties).
Also here is a short explanation on how bindings are constructed: A binding consists of a source and a Path relative to that source, by default the source is the current DataContext. Sources that can be set explicitly are: Source, ElementName & RelativeSource. Setting any of those will override the DataContext as source.
So if you use a source like RelativeSource and want to access something in the DataContext on that level the DataContext needs to appear in the Path.
This may be considered unrelated by most, but this search is only 1 of 3 results that you'll find searching for data binding commands to controls inside a data template--as it relates to Xamarin Forms. So, maybe it'll help someone now-a-days.
Like me you may wonder how to bind commands inside a BindableLayout. Credit jesulink2514 for answering this at Xamarin Forums, where it's probably overlooked by many because of all the comments. Here's his solution, but I'm including the link below:
<ContenPage x:Name="MainPage">
<ListView Grid.Row="1"
ItemsSource="{Binding Customers}"
VerticalOptions="Fill"
x:Name="ListviewCustomer">
<ListView.ItemTemplate>
<DataTemplate>
<Label Text="{Binding Property}"/>
<Button Command="{Binding BindingContext.ItemCommand, Source={x:Reference MainPage}}"
CommandParameter="{Binding .}">Click me</Button>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage>
https://forums.xamarin.com/discussion/comment/217355/#Comment_217355

AutoCompleteBox in silverlight toolkit for windows phone wrong display

I'm having a problem with the autocompletebox from the toolkit for windows phone. I bind it to some data, then when i press it and start typing, it discovers some items but they are displayed wrong (the list is shown separated from the box, and also if i click on any item, nothing happens. If i click where the item would be supposed to be (for example, right on the top of the box), then it gets selected. It looks like a rendering problem (bug?)) but perhaps i'm doing something wrong. Here's the code for the box :
<DataTemplate x:Key="DataTemplate1">
<ContentControl Content="{Binding Name}" Margin="8,7"/>
</DataTemplate>
<toolkit:AutoCompleteBox ItemsSource="{Binding}" x:Name="txtSelectValues" MinWidth="250" Margin="0,0,0,0" ItemTemplate="{StaticResource DataTemplate1}" VerticalAlignment="Top" />
Found it. It's a bug with the AutoCompleteBox. When inside a scrollviewer control, the dropdown gets messed up and displayed in an incorrect position
Its not just that is also to do with being placed inside of a Pivot/Panaroma as well as the scrollviewer, the silverlight gurus have stated they haven't a timeline for the fix for the Pivot control, and there is a nasty hack
http://silverlight.codeplex.com/workitem/7574
I think the answer might just be that you shouldn't be using a ContentControl directly used like this. Try using something like a TextBlock instead - e.g.:
<DataTemplate x:Key="DataTemplate1">
<TextBlock Text="{Binding Name}" Margin="8,7"/>
</DataTemplate>
If that's not the answer, then try pulling back to a simple example - especially removing all the Margin's, Width's, Alignment's, etc - then put them back in one-by-one to work out and understand what is causing the effect you are seeing.

How to use Pivot Effectively?

I have following data structure in my WP7 app. And I'm generating three PivotItems through databinding, contents of binding. Interesting part is when Binding happens for Pivot items contents(Items) are queried for three time and again selection changes.
Is there anything I'm doing wrong?
Code:
<controls:Pivot Title="{StaticResource ApplicationName}" ItemsSource="{Binding Folders}" SelectedItem="{Binding SelectedFolder, Mode=TwoWay}" Name="_pivot">
<controls:Pivot.ItemTemplate>
<DataTemplate>
<ListBox DataContext="{Binding Source={StaticResource Locator}}" ItemsSource="{Binding ThingsListViewModel.Items}" />
</DataTemplate>
</controls:Pivot.ItemTemplate>
I have three folders items, when Pivot control is created ThingsListViewModel.Items property executed thrice, and once every time selection changes.
I'm expecting ThingsListViewModel.Items to execute only selection chage on Pivot control.
I think you need to listen to the LoadedPivotItem and Loaded events of the pivot. The Loaded event will always load the first PivotItem (LoadedPivotItem) will not be called. The LoadedPivotItem is called when the user swipes to another PivotItem.
Based on these events you should then run your queries for the currently SelectedPage. You may also want a flag to indicate once you have loaded the data for each Pivot to avoid running the queries again.

Categories