Using Sample Data saved as XAML, at Design Time in UWP - c#

I am reading this article and trying to use a sample data for ListView to display the data at the design time.
However, I cannot make it, and am seeing an error saying that it cannot build the DataContext in the ListView at the highlighted part below.
d:DataContext="{d:DesignData SampleData.xaml}"
Visual Studio 2019 16.9.1
The files are as below. These have been saved in one folder in flat.
Could you help me to know the appropriate way of such using of sample data?
MainPage.xaml:
<Page
x:Class="App1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
d:DesignWidth="459" d:DesignHeight="262">
<Grid>
<ListView d:DataContext="{d:DesignData SampleData.xaml}"
ItemsSource="{Binding Mode=OneWay}">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBox Text="-- " />
<TextBox Text="{Binding Name}" />
<TextBox Text="{Binding Age}" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</Page>
SampleData.xaml (marked as DesignData for the build action):
<sample:PersonCollection
xmlns:sample="using:App1">
<sample:Person Name="John Doe" Age="20" />
<sample:Person Name="Jane Doe" Age="30" />
</sample:PersonCollection>
Person.cs:
namespace App1 {
public class Person {
public string Name { get; set; }
public int Age { get; set; }
public Person() {
}
}
}
PersonCollection.cs:
using System.Collections.ObjectModel;
namespace App1{
public class PersonCollection : ObservableCollection<Person> {
public PersonCollection(): base(){
}
}
}

Using Sample Data saved as XAML, at Design Time in UWP
I'm afraid you can't use Xaml design data for UWP app, derive from this document,
One good option is the Create Sample Data from Class feature in Blend for Visual Studio. You can find that command on one of the buttons at the top of the Data panel. Unfortunately,
The Data panel in Blend is supported only for projects that target .NET Framework. It's not supported for UWP projects or projects that target .NET Core.

Related

DataTemplateSelector that's using boolean value as an object reports an issue in XAML Designer

DISCLAIMER
This issue is only reported in the XAML Designer itself, when I run the application in debug mode, I can't see any XAML Binding issues at a runtime, and the ContentPresenter works as expected.
DataTemplateSelector:
internal sealed class BooleanDataTemplateSelector : DataTemplateSelector
{
#region Public Properties
public DataTemplate? FalseDataTemplate { get; set; }
public DataTemplate? TrueDataTemplate { get; set; }
#endregion Public Properties
#region Public Methods
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
if (FalseDataTemplate == null || TrueDataTemplate == null) return new DataTemplate();
var isLoading = (bool)item;
return isLoading ? TrueDataTemplate : FalseDataTemplate;
}
#endregion Public Methods
}
ResourceDictionary which holds the template and selector with x:Key:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mat="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:pages="clr-namespace:ComatiQ.Configurator.Client.Core.ViewModels.Pages;assembly=ComatiQ.Configurator.Client.Core"
xmlns:resx="clr-namespace:ComatiQ.Configurator.Client.Wpf.Strings.Pages.HomePage"
xmlns:selectors="clr-namespace:ComatiQ.Configurator.Client.Wpf.Selectors">
<DataTemplate
x:Key="ContentLoadingTemplate"
DataType="{x:Type pages:HomePageViewModel}">
<mat:Card>
<StackPanel
HorizontalAlignment="Center"
VerticalAlignment="Center"
Orientation="Vertical">
<TextBlock
Margin="0,0,0,10"
Style="{StaticResource MaterialDesignHeadline6TextBlock}"
Text="{x:Static resx:HomePage.RouteOperation_Loading}" />
<ProgressBar
Height="20"
IsIndeterminate="True"
Style="{StaticResource MaterialDesignLinearProgressBar}" />
</StackPanel>
</mat:Card>
</DataTemplate>
<DataTemplate
x:Key="NullTemplate" />
<selectors:BooleanDataTemplateSelector
x:Key="LoadingTemplateSelector"
FalseDataTemplate="{StaticResource NullTemplate}"
TrueDataTemplate="{StaticResource ContentLoadingTemplate}" />
</ResourceDictionary>
HomePageView.xaml part of the code which reports an issue:
<Grid
Grid.Row="1"
Grid.Column="1"
Margin="2.5"
Panel.ZIndex="1">
<!-- CONTENT VIEWER -->
<ContentPresenter
Panel.ZIndex="0"
Content="{Binding DisplayedViewModel}"
ContentTemplateSelector="{StaticResource ViewContentTemplateSelector}" />
<!-- CONTENT LOADING INFO -->
<ContentPresenter
Panel.ZIndex="1"
Content="{Binding IsRouteLoading}"
ContentTemplateSelector="{StaticResource LoadingTemplateSelector}" />
</Grid>
The ContentPresenter under the reports:
**Severity Code Description Project File Line Suppression State
Error XDG0066 Object reference not set to an instance of an object. ComatiQ.Configurator.Client.Wpf D:\Programming\Projects\DomatiQ DALI Configurator\DomatiQ DALI Configurator\ComatiQ.Configurator.Client.Wpf\Views\Pages\HomePageView.xaml 138
**
I created a lot of software solutions for my company, which are WPF based, yet I never encountered this particular issue. Is this a Visual Studio 2022 XAML Designer Bug, because otherwise I've no idea why I get any errors.
Turns out it is a Visual Studio 2022 XAML Designer bug.
I'm now using Rider which I prefer anyway, and use VS2022 just to apply formatting when creating PR's.

WinUI ListView ObservableColellection binding not working

I'm learning the new WinUI platform together with XAML and GUI programming in C# and I'm not sure if I correctly understand how the bindings and updates work, but I can't get the following code (minimal working example) to work:
MainPage.xaml
<Page
x:Class="uitest.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
<ListView ItemsSource="{x:Bind Items, Mode=OneWay}"></ListView>
<Button Content="Add" Click="Button_OnClick"></Button>
</StackPanel>
</Page>
MainPage.xaml.cs
using System.Collections.ObjectModel;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
namespace uitest
{
public sealed partial class MainPage : Page
{
public ObservableCollection<string> Items = new ObservableCollection<string>();
public MainPage()
{
this.InitializeComponent();
Items.Add("A");
Items.Add("B");
}
private void Button_OnClick(object sender, RoutedEventArgs e)
{
Items.Add("Next");
}
}
}
When I start the application, I see a list with two items but when I click the button nothing happens. I wanted to use the Live Visual Tree for debugging but it's not working for some reason.
I opened an issue on the official WinUI repository for this and apparently it's a compatibility fault in the latest WinUI 3 preview. I should also note this does not work only on the UWP platform but it works on the Desktop (Win32).

WPF plugin architecture itemscontrol binding not working

We encountered an interesting behavior on .Net 4.5 (4.6.2 also tested).
The project has multiple plugin dlls.
main exe will load DataTemplates (view) and ViewModels from DLLs using MEF.
if StepView and StepVm and main frame code are in one project (not using MEF), The 2 buttons I show below are working.
if move StepView and StepVm to plugin dll, only second button will work. First one shows binding error in output console. need to talk to manager if I can post error msg here, just wpf standard binding error.
Can anyone share some insights here?
Thanks.
StepView
<UserControl
x:Class="StepView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:ScriptHighlighter"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
d:DataContext="{d:DesignInstance local:StepVm}"
d:DesignHeight="450"
d:DesignWidth="800"
mc:Ignorable="d">
<Grid>
<ItemsControl x:Name="XItemsControl" ItemsSource="{Binding Names}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel>
<Button
Content="Not Wokring in plugin mode"
Command="{Binding ElementName=XItemsControl, Path=DataContext.DeleteCommand}"
CommandParameter="{Binding}" />
<Button
Content="Wokrs in plugin mode"
Command="{Binding Path=DataContext.DeleteCommand, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}, Mode=FindAncestor}}"
CommandParameter="{Binding}" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
StepVm
public class StepVm:ViewModelBase
{
public StepVm()
{
this.Names = new List<string>(){"1", "2", "3"};
}
public List<string> Names { get; set; }
public ICommand DeleteCommand => new RelayCommand<string>(n =>
{
Debug.WriteLine($"logic to delete {n}");
});
}
Because MEF loads your UserControl dynamically into the Visual Tree, you are likely to have issues with NameScope, which I think is whats happening here.
WPF XAML Namescopes
To be honest, your use of ElementName binding is problematic, because your are in a DateTemplate which is an encapsulation boundary, so although it works outside MEF its not a typically supported scenario.

Windows 10 Universal Compiled binding (x:Bind) conflict with ViewModel

I want to bind an element in a page to dependency property in code behind with compiled binding and same time bind another element to ViewModel with usual binding. But it gives a runtime error.
Here is my xaml code.
<Page
x:Class="XbindingProblem.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:XbindingProblem"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
DataContext="{Binding Main, Source={StaticResource Locator}}"
mc:Ignorable="d">
<Page.Resources>
<DataTemplate x:Key="UserDataTemplate" x:DataType="local:User">
<StackPanel>
<TextBlock Text="{x:Bind Name}" />
<TextBlock Text="{x:Bind Age}" />
</StackPanel>
</DataTemplate>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<StackPanel>
<TextBlock Text="{Binding Title}"/>
<ContentPresenter ContentTemplate="{StaticResource UserDataTemplate}" Content="{x:Bind CurrentUser, Mode=OneWay}"/>
</StackPanel>
</Grid>
Here CurrentUser is dependency property which is initially null and then change in run time. This gives following runtime error.
Incorrect type passed into template. Based on the x:DataType global::XbindingProblem.User was expected.
The problem is it passes the ViewModel into UserDataTemplate instead of CurrentUser dependency property when CurrentUser is null.
Can anyone have a good explanation on this problem?
If you remove DataContext="{Binding Main, Source={StaticResource Locator}}", it will work. Why? because {x:Bind CurrentUser} is looking for a property called CurrentUser sitting inside your MainPage.xaml.cs. Since the CurrentUser is indeed a dependency property of your page, it will just work.
However, by specifying the DataContext of your page, the x:Bind is now excepting a CurrentUser property inside your MainViewModel instance, and of course it's not going to find it, so a compile-time error will be thrown.
One possible fix is to set the this.CurrentUser really early, even before calling InitializeComponent.
this.CurrentUser = new User();
InitializeComponent();
But this is IMHO not the the right way of doing things, as it's basically a racing game - it tries to populate the ContentPresenter before the DataContext gets updated, and in the end you will end up having the TextBlock (of which Text binds to Title) and the ContentPresenter attached to different contexts!
So ask yourself why you need to create a dependency property for CurrentUser inside a Page object, instead of having a normal property (with INotifyPropertyChanged implementation) sitting inside your MainViewModel? I'd prefer the latter, 'cause it's more semantically correct.
The question is interesting, what I have done is just remove the datacontext and this is the code behind is similar to yours:
public sealed partial class BlankPage1 : Page
{
public User CurrentUser
{
get { return (User)GetValue(CurrentUserProperty); }
set { SetValue(CurrentUserProperty, value); }
}
// Using a DependencyProperty as the backing store for CurrentUser. This enables animation, styling, binding, etc...
public static readonly DependencyProperty CurrentUserProperty =
DependencyProperty.Register("CurrentUser", typeof(User), typeof(BlankPage1), new PropertyMetadata(null));
public BlankPage1()
{
this.InitializeComponent();
CurrentUser = new User() { Name = "Hello", Age = "20" };
}
}
public class User
{
public String Name { get; set; }
public String Age { get; set; }
}
might be you have the User class in another namespace or have another class in the typeof(...) of the dependency property. Because I tested that and works. The DataContext of the page can be whatever you want it won't affect.
Then I added the datacontext just to test:
<Page.DataContext>
<local:Main/>
</Page.DataContext>
and the code just for testing:
public class Main
{
public String Title { get; } = "title";
public User MainUser { get; set; }
}
And it does not throws any exception, appears the Main data and the CurrentUser data.
UPDATE. The error happens when the User is null so it is like the x:Bind is null it propagates to the Binding,To solve that (it was tough):
<Page x:Name="Root"
x:Class="Deletetb.BlankPage1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Deletetb"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" >
<Page.DataContext>
<local:Main/>
</Page.DataContext>
<Page.Resources>
<DataTemplate x:Key="UserDataTemplate" x:DataType="local:User">
<StackPanel>
<TextBlock Text="{x:Bind Name}" />
<TextBlock Text="{x:Bind Age}" />
</StackPanel>
</DataTemplate>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<StackPanel DataContext="{x:Null}">
<TextBlock Text="{Binding DataContext.Title, ElementName=Root}" />
<ContentPresenter ContentTemplate="{StaticResource UserDataTemplate}" Content="{x:Bind CurrentUser, Mode=OneWay}"/>
</StackPanel>
</Grid>
</Page>
Where is binding defined (TextBlock) I set the datacontext to null in the parent container (StackPanel) and bind by element name, and it does not crash, also I added a wait by code to test and set the Current User and it works. That was a challenge. hope it also works for you.
Although it breaks the idea of MVVM a bit, you can add a property to your page like this:
public MainViewModel viewModel => DataContext as MainViewModel;
And then in the XAML code reference the page property
<ContentPresenter Content="{x:Bind viewModel.CurrentUser, Mode=OneWay}" />

Need some guidance for this simple WPF single window load page

I need to get up to speed with some intermediate things in WPF and I'm building this small application as my learning grounds.
I have a collection of five pictures. Each picture has certain data tied to it: owner, date, size, etc.
I'd like to be able to click that picture and load that information into display in the same window. I do NOT want to load the information in a new opened window.
Any suggestions on what to search for, or even a small verbal walk through of the process?
I'm using a Frame to load the initial five picture, but I don't know how to capture the click on the main parent window if the click is being registered inside the user control.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="22" />
<RowDefinition />
</Grid.RowDefinitions>
<Menu Grid.Row="0">
<MenuItem Header="_File" />
<MenuItem Header="_Edit" />
<MenuItem Header="_View" />
<MenuItem Header="_Help" />
</Menu>
<Frame Grid.Row="1" Name="contentFrame" Source="Roster.xaml" />
</Grid>
Then in Roster.xaml:
<UserControl x:Class="OracleOfLegends.Roster"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
//Lots of goodies here.
</UserControl>
You never mentioned about you Model Object ... so i will assume it as
Model
public class MyPicture : INotifyPropertyChanged
{
private string url;
private string name;
// Other fields
public Url
{
get{ return value;}
set{url=value;}
OnPropertyChanged("Url")
}
}
//Do same for other fields . I leave the implementation if INPC on you
ViewModel MyPictureListViewModel
public MyPictureListViewModel:INotifyPropertyChanged
{
ObservableCollection<MyPictureList> picList;
public PicList
{
get{return value;}
set{piclist=value;}
OnPropertyChanged("PicList")
}
//Fill the list with some methods... it depends on you
}
/// <summary>
/// Interaction logic for MyUserControl.xaml
/// </summary>
public partial class PicListDisplay
{
private readonly MyPictureListViewModel
myPictureListViewModel;
/// <summary>
/// PicListDisplay
/// </summary>
public PicListDisplay()
{
myPictureListViewModel= new MyPictureListViewModel();
this.DataContext = myPictureListViewModel;
InitializeComponent();
}
}
I would prefer to use ListView
<ListView Name="myPicListView" ItemsSource={Binding PicList}>
<ListView.ItemTemplate>
<Datatemplate>
<UserControls:Roster/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
// Here i am just Displaying the name you can put any control you want
<StackPanel DataContext="{Binding Path=SelectedItem,Elementname=myPicListView}">
<TextBlock Text="{Binding Path=Name}"></TextBlock>
</StackPanel> </UserControl>
Here i have made a listView and then on selecting the listview you can get the Data On the same window.... also you can create you Own view like that of Windows Explorer or else and use inside a list View
You can do pretty much the same thing in WPF using a Frame which you can navigate to a new UserControl containing the information.

Categories