DataBinding and Incomplete Microsoft Documentation - xaml

Basically, I'm working through the Microsoft tutorial on WPF:
https://learn.microsoft.com/en-us/dotnet/opbuildpdf/framework/wpf/data/toc.pdf?branch=live
I get to page 8, and (in my opinion) Microsoft screwed up. They don't give any C# code-behind that is necessary to run the following XAML:
<DockPanel
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:c="clr-namespace:SDKSample">
<DockPanel.Resources>
<c:MyData x:Key="myDataSource"/>
</DockPanel.Resources>
<DockPanel.DataContext>
<Binding Source="{StaticResource myDataSource}"/>
</DockPanel.DataContext>
<Button Background="{Binding Path=ColorName}" Width="150" Height="30">
I am bound to be RED!</Button>
</DockPanel>
I follow their description as best as possible, but all I get is this following error message.
The name "MyData" does not exist in the namespace "clr-namespace:SDKSample".
I do what I'm supposed to do: create a c# file, using "Add New Item" and build it, but still that error code pops up again. To save people from having to look up the documentation, here's what they ask for:
Consider the following example, in which the binding source object is
a class named MyData that is defined in the SDKSample namespace. For
demonstration purposes, MyData class has a string property named
ColorName, of which the value is set to "Red". Thus, this example
generates a button with a red background.
I've looked in the various SDK's for this example, hoping I'd find the mysterious C# file somewhere, but alas I can't find it. It seems like Microsoft forgot a link. You know, even if it is somewhere in an SDK, it is extremely hard to find. As someone in a learning-mode, I'd hope that all the gritty details would be provided in the documentation, not just the quote from above, which doesn't go into any details as to where to put the C# file, how you are supposed to build so it will properly get registered as existing.
So, if anyone can find a nice description as to how to get the XAML code to work, by creating a C# class named "MyData" in a "SDKSamples" namespace, I'd be very appreciative.

the xaml works when you add the following:
namespace SDKSample
{
public class MyData
{
public Brush ColorName { get; set; } = Brushes.Red;
}
}

<Window x:Class="StackExchangeQuestion.MainWindow"
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"
xmlns:local="clr-namespace:StackExchangeQuestion"
mc:Ignorable="d"
xmlns:c="clr-namespace:SDKSample"
Title="MainWindow" Height="350" Width="525">
<DockPanel >
<DockPanel.Resources>
<c:MyData x:Key="myDataSource"/>
</DockPanel.Resources>
<DockPanel.DataContext>
<Binding Source="{StaticResource myDataSource}"/>
</DockPanel.DataContext>
<Button Background="{Binding Path=ColorName}" Width="150" Height="30">
I am bound to be RED!</Button>
</DockPanel>
</Window>
I'd like to add that Microsoft assumes that you have all the stuff between <Window x:Class and Width="525"> already there. It's kind of sloppy work to just leave out that massive detail in their documentation. Thanks to Milan for getting me to look at what should go inside the <Window>...</Window> part of the code.
Also, in the interest of completeness, the C# code:
using System.Windows;
using System.Windows.Media;
namespace StackExchangeQuestion
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
}
namespace SDKSample
{
public class MyData
{
public Brush ColorName { get; set; } = Brushes.Red;
}
}

Related

System.Type as property of converter - only works with unused property in code behind

I have a IValueConverter that has a System.Type property which is set in XAML.
Converter:
internal class EnumTypeConverter : IValueConverter
{
public Type TypeToDisplay { get; set; }
public object Convert(object value, Type targetType, object parameter, string language)
{
return TypeToDisplay?.FullName;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
XAML:
<Page
x:Class="UWPSystemTypeConverterTest.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"
xmlns:converter="using:UWPSystemTypeConverterTest.Converter"
xmlns:enums="using:UWPSystemTypeConverterTest.Enum"
mc:Ignorable="d">
<Page.Resources>
<converter:EnumTypeConverter x:Key="Converter" TypeToDisplay="enums:CustomEnum" />
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<TextBlock Text="{Binding Converter={StaticResource Converter}}" />
</Grid>
</Page>
When I run the application, I get following error:
Windows.UI.Xaml.Markup.XamlParseException: 'The text associated with
this error code could not be found.
Failed to create a
'UWPSystemTypeConverterTest.Converter.EnumTypeConverter' from the text
'enums:CustomEnum'. [Line: 14 Position: 56]'
If I add a property of type CustomEnum to the code- behind file, which is never used, the application works.
the changed code- behind- File:
public sealed partial class MainPage : Page
{
public CustomEnum WithThisPropertyTheAppWorks { get; set; }
public MainPage()
{
InitializeComponent();
this.DataContext = this;
}
}
The complete project for reproduction is here: https://github.com/SabotageAndi/UWPSystemTypeConverterTest
Line to uncomment is https://github.com/SabotageAndi/UWPSystemTypeConverterTest/blob/master/UWPSystemTypeConverterTest/MainPage.xaml.cs#L13
I suspect that an optimiser of UWP is causing this problem.
Is this really the case?
How can I fix the error without the unused property in the code-behind file?
Targeting UWP Build 10240, a viable work around is to add a dummy instance of the targeted enum in static resources of the page before instantiating the converter.
<Page.Resources>
<enums:CustomEnum x:Key="WorkAround">CustomEnumValue</enums:CustomEnum>
<converter:EnumTypeConverter x:Key="Converter" TypeToDisplay="enums:CustomEnum" />
</Page.Resources>
Info from a MSFT employee on a MVP mailing list:
This behaviour is a current limitation of UWP.
The XAML compiler and the runtime don't support System.Type- typed properties. So the needed metadata is not generated and the runtime can not convert the string to the type.
But because of the public properties on the code-behind, the compiler generates the needed metadata now. I am not that happy with the work around, but it is better than other solutions (e.g. a string property with the fullname to the type).

Page with type parameter

I would like to use new feature of UWP -> x:Bind. In order to that, all my pages need to have ViewModel property (as described in tutorials).
To avoid code duplicity, I have established base class as follows:
public abstract class BasePage<TBaseVM> : Page, where TBaseVM : BaseVM
{
public TBaseVM VM { get; private set; }
protected BasePage()
{
DataContextChanged += (s, e) => VM = e.NewValue as TBaseVM;
}
}
As you can see this BasePage class contains property called "VM" and property is of type BaseVM. Hence, I don't need to define VM property on each derived class.
Then I created derived page 'MainPage' defined in xaml as follows:
<pages:BasePage
x:Class="Realarm.View.Pages.MainPage"
x:TypeArguments="viewModel:MainVM">
By doing that, even Resharper's Intellisense offers me properties from "MainVM" in MainPage.xaml, thus is can write:
<ListView ItemsSource="{x:Bind VM.AlarmsVM}">
Unfortunately, when I try to build the project, I get error in MainPage.g.i.cs:
Severity Code Description Project File Line
Error CS0305 Using the generic type 'BasePage' requires 1 type arguments Realarm D:...\Realarm\obj\x86\Debug\View\Pages\MainPage.g.i.cs 13
Any help?
I got this working using Xamarin.Forms.
Base Page:
public abstract class BaseContentPage<TViewModel> : ContentPage where TViewModel : BaseViewModel, new()
HomePage.cs:
public partial class HomePage : BaseContentPage<HomeViewModel>
HomePage.xaml:
<d:BaseContentPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="clr-namespace:Sample.Pages;assembly=Sample"
xmlns:vm="clr-namespace:Sample.ViewModels;assembly=Sample"
x:Class="Sample.Pages.HomePage"
x:TypeArguments="vm:HomeViewModel">
<ContentPage.Content>
</ContentPage.Content>
</d:BaseContentPage>
Just add a x:TypeArguments definition at the top of the XAML:
<v:BasePage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:v="clr-namespace:YourApp.Views"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="clr-namespace:YourApp.ViewModels"
mc:Ignorable="d"
x:TypeArguments="vm:HomeViewModel"
x:Class="YourApp.MainPage">
Worked for me as well when I set the BindingContext as given below in Base Page's constructor:
public BasePage()
{
BindingContext = new TBaseVM();
}

Why is my DependencyProperty not accessible?

I have a user control called AlarmSettings, the user control's resource dictionary contains an instance of my custom class "AlarmClock", the AlarmClock has a dependency property called AlarmName, why do I get the error Error "The member "AlarmName" is not recognized or is not accessible."
This is my user control:
<UserControl x:Class="ChangeSet.AlarmSettings"
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"
xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit"
xmlns:alarm="clr-namespace:ChangeSet.Alarm;assembly=ChangeSet"
mc:Ignorable="d"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
d:DesignHeight="480" d:DesignWidth="480" >
<UserControl.Resources>
<alarm:AlarmClock x:Key="alarmClock" AlarmName="{Binding ElementName=AlarmSettings, Path=Name}"/>
</UserControl.Resources>
This is my AlarmClock class:
public class AlarmClock: DependencyObject
{
public AlarmClock()
{
PopulateSettingsOptions();
}
public string AlarmName
{
get { return GetValue(AlarmNameProperty).ToString(); }
set { SetValue(AlarmNameProperty, value); }
}
public static readonly DependencyProperty AlarmNameProperty =
DependencyProperty.Register("AlarmName", typeof(string), typeof(AlarmClock), new PropertyMetadata("DefaultAlarm"));
Note: I'm trying to bind the AlarmName to the Name property of the AlarmSettings user control but even if I remove the binding and try to set the AlarmName dependency property to a string I will still get the same error.
i had moved my project from one Location to another and got the same issue with dependency property when I opened it again. I just rebuild it and errors got resolved.
I had the same problem when accessing a dependency property from XAML in Visual Studio. I just rebuilt the project.
This warning popped up again recently for me. Since everything seemed correct, and whenever XAML gives me this kind of weird behavior, I resort to removing bin & obj folders, which did the trick (once again).
What is the DataContext of your userControl?
Add an empty constructor to your class alarmClock.
Open the "Configuration Manager..." in the VS. Check if your projects are in the same platform, e.g: x64.

Populating a property of type ObservableCollection in XAML with static resources

I have created a class that contains a property of type ObservableCollection. I am trying to create an instance of the class in XAML and fill this property with members. I keep getting an exception that class T can not be converted to ObservableCollection, but this exception only occurs when I am trying to populate the list with elements that were declared as static resources.
Anybody has an idea why?
The code is as follows:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mseg="clr-namespace:SegApp.Model.DataEntities.Segments;assembly=SegApp.Model.Silverlight">
<mseg:Dot xKey="d1"/>
<mseg:Dot xKey="d2"/>
<mseg:Dot xKey="d3"/>
<mseg:Dot xKey="d4"/>
<mseg:Segment xKey="seg1">
<mseg:Segment.Dots>
<StaticResource ResourceKey="d1"/>
<StaticResource ResourceKey="d2"/>
<StaticResource ResourceKey="d3"/>
<StaticResource ResourceKey="d4"/>
</mseg:Segment.Dots>
</mseg:Segment>
</ResourceDictionary>
The Class definition is:
public class Segment : Part
{
public ObservableCollection<Dot> Dots { get; set; }
public Segment()
{
Dots = new ObservableCollection<Dot>();
}
}
And the exception says:
"
Object of type bla.bla.bla.Dot can not
be converted to type
System.Collections.ObjectModel.ObservableCollection'1[bla.bla.bla.Dot]
"
Any ideas?
As is your code, each element of the collection must be a Dot, not a resource...
Each entry of the list in your xaml code must be something like
or perhaps try
somevalue
or
{staticResource xxx }
But there is still a problem. The 1st syntax is ok, the second can work if there is a simple content for Dot, but the 3rd can't run : tag means "create an instance of Dot". And a StaticResource means "create an instance of.. and give it a key".
So last syntax will certainly not work cause you can replace the instance created by the tag with the instance coming from the resource...
But give it a try. The main problem in your code is than you're trying to feel a collection of Dot with Resource, that can't work and the compiler is not ok.. try using tag to create entry. And then play a bit to see if you can refer the resources somewhere in these tags..
In order to use collections XAML syntax change your property and remove it's setter:
public class Segment : DependencyObject
{
private readonly ObservableCollection<Dot> _dots = new ObservableCollection<Dot>();
public ObservableCollection<Dot> Dots
{
get { return _dots; }
}
}

XmlnsDefinitionAttribute combined with x:Name causes compilation error with code generation

I have and issue with using the XmlnsDefinition attribute within a silverlight 4 assembly.
Here's the test case:
In AssemblyInfo.cs of the silverlight project I add the following:
[assembly: XmlnsDefinition("urn:foo", "SilverlightApplication1")]
[assembly: XmlnsDefinition("urn:foo", "SilverlightApplication1.SomeNamespace")]
I edit MainPage.xaml.cs and to make it look like so:
namespace SilverlightApplication1
{
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
}
}
}
namespace SilverlightApplication1.SomeNamespace
{
public class SomeControl : ContentControl
{
}
}
Now in MainPage.xaml I have the following:
<UserControl x:Class="SilverlightApplication1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:foo="urn:foo">
<Grid>
<foo:SomeControl>
<TextBlock Text="Hello World"/>
</foo:SomeControl>
</Grid>
</UserControl>
This compiles and runs fine. The problem occurs when I add the x:Name attribute to the SomeControl tag.
This does not compile:
<foo:SomeControl x:Name="bar">
<TextBlock Text="Hello World"/>
</foo:SomeControl>
Looking at the .g.i.cs file that gets generated, the control is declared as
internal SomeControl bar;
The file is missing either the using statement or the full type name. I've also tried this in WPF and the results are the same. Can anyone tell me what, if anything, I'm doing wrong?
I have the same issue. Based on my searching, it looks like this is not currently supported.
http://forums.silverlight.net/forums/t/84877.aspx
http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/7e7a032a-dad3-4e02-9e5a-d73e346b75ed/