Windows Store project in C++/CX. I've placed an instance of the custom C++ class on a XAML page. I've marked it with a namespace. The project builds. Yet the design surface does not display the control, claims it's not present in the assembly. The XAML goes like this:
<UserControl
x:Class="MyApp.Foo"
xmlns:local="using:MyApp"
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"
d:DesignHeight="300"
d:DesignWidth="400" Loaded="OnLoaded">
...
<local:MyControl x:Name="Bar" HorizontalAlignment="Left" VerticalAlignment="Top"/>
The MyControl class is declared in code like this:
[Windows::Foundation::Metadata::WebHostHidden]
public ref class MyControl sealed : Windows::UI::Xaml::Controls::Canvas
{
...
};
It has a public default contructor with no parameters. What's wrong here, please?
Related
I want to add a variable to my xaml.
My xaml looks like this
<Page
x:Class="UwpTest.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:UwpTest"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:system="using:System"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Page.Resources>
<system:String x:Key="var1">1.2</system:String>
</Page.Resources>
<Grid>
</Grid>
</Page>
When run, I get runtime error.
Microsoft.UI.Xaml.Markup.ReflectionHelperException
HResult=0x80131500
Message=Error in reflection helper. Please add '<PropertyGroup><EnableTypeInfoReflection>false</EnableTypeInfoReflection></PropertyGroup>' to your project file.. Created Xaml type 'String' has a different name than requested type 'System.String'
Source=Windows
StackTrace:
at Windows.UI.Xaml.Application.LoadComponent(Object component, Uri resourceLocator, ComponentResourceLocation componentResourceLocation)
at UwpTest.MainPage.InitializeComponent() in D:\Dev\UwpTest\UwpTest\obj\x86\Debug\MainPage.g.i.cs:line 33
at UwpTest.MainPage..ctor() in D:\Dev\UwpTest\UwpTest\MainPage.xaml.cs:line 27
I want to add a variable to my xaml
You could add x:String into resource as variable for example
<x:String x:Key="var1">Hello</x:String>
For more please refer to XAML intrinsic data types
I have a ListView with this item template:
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<views:ProjectListEntry />
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
ProjectListEntry is fairly complex and is used in another ListView, so I have it in its own file. I've set it up like this:
<ContentView
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
...
BindingContext="{x:Static vms:DesignTimeData.ProjectListEntryVm}">
As you can see, to get binding Intellisense (using ReSharper), I tried to set BindingContext to a static member on the DesignTimeData class. This works fine for my Pages (where I replace the BindingContext at runtime), but for ContentViews used in ListViews, the ContentView's BindingContext seems to be inherited (from the ViewCell, I guess). This means that the explicit BindingContext on my ContentView will actually override the BindingContext set on the ViewCell by the ListView, and all my list elements will reflect the static design-time data at runtime. But if I remove the BindingContext, I get no intellisense for the members I bind to inside the ContentView file.
Is there a simple way to get Intellisense for bindings in a ContentView like this?
(As mentioned, I can't inline the ContentView in the ListView definition, because the ContentView is fairly complex and used in several lists. I also can't use some kind of VM locator, because although I'm using bindings, I'm not using "full" MVVM - I'm using a Redux-like architecture instead. And I guess a VM locator wouldn't work for this case anyway for the same reasons the above doesn't work.)
(Cross-posted from the Xamarin Forums where I didn't get any reply.)
This solution seems to work fine. In short: Add
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
and use d:DataContext instead of BindingContext. Going from the example above, it should look like this:
<ContentView
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
...
BindingContext="{x:Static vms:DesignTimeData.ProjectListEntryVm}">
This leads to working binding intellisense from ReSharper and does not cause issues when run.
In a UWP app, I have a custom UserControl with some child controls (text boxes, labels, etc.). I have a Page that includes that UserControl as a child element. Now, I want to place a button below that UserControl and align it with one of the control's child text boxes using a RelativePanel. I can't figure out a way to access the child element.
For example, I have a custom control:
<UserControl
x:Class="Sandbox.FooControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Sandbox"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">
<Grid>
<TextBox
x:Name="TheTextBoxIWantToAlignWith"
x:FieldModifier="public"/>
</Grid>
And now I want to align with "TheTextBoxIWantToAlignWith":
<UserControl
x:Class="Sandbox.FooParentControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Sandbox"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">
<RelativePanel>
<local:FooControl
x:Name="Foo"
RelativePanel.AlignTopWithPanel="True"
RelativePanel.AlignHorizontalCenterWithPanel="True"/>
<Button
RelativePanel.Below="Foo"
RelativePanel.AlignLeftWith="Foo.TheTextBoxIWantToAlignWith"/> <!-- This doesn't work -->
</RelativePanel>
Obviously this doesn't work ("RelativePanel error: The name 'Foo.TheTextBoxIWantToAlignWith' does not exist in the current context."). I tried:
Setting the FieldModifier to public on the child TextBox
Exposing the TextBox as a public property in code-behind
Exposing the TextBox as a DependencyProperty in code-behind
I really want to avoid flattening out the UserControl into the parent page because it can be reused elsewhere. Is there any way to do this?
I ended up working around the issue with code-behind, similar to Lindsay's suggestion. I hooked into the LayoutUpdated event, which calculated and set the margin. Something like this:
private void AlignButton()
{
var transform = Foo.TheTextBoxIWantToAlignWith.TransformToVisual(RootPanel);
var textBoxRightEdge = transform .TransformPoint(new Point()).X + Foo.TheTextBoxIWantToAlignWith.ActualWidth;
var rightMargin = RootPanel.ActualWidth - textBoxRightEdge;
if (Math.Abs(TheButtonIWantToAlign.Margin.Right - rightMargin) >= 1)
TheButtonIWantToAlign.Margin = new Thickness(0, 0, rightMargin, 0);
}
This is a follow up question related to a control that needs to intercept when common control properties changes (Inherit UserControl and hooking up to basic property events).
When any base property changes (foregound, font style, size...), I need to invalidate the canvas and redraw the content.
I've ended up with calling this method inside the UserControl constructor:
RegisterPropertyChangedCallback(DependencyProperty dp, DependencyPropertyChangedCallback callback);
For example:
RegisterPropertyChangedCallback(ForegroundProperty, OnPropertyChanged);
RegisterPropertyChangedCallback(FontFamilyProperty, OnPropertyChanged);
RegisterPropertyChangedCallback(FontSizeProperty, OnPropertyChanged);
Inside OnPropertyChanged I proceed to rewire some property and invalidate the canvas in order to update the picture.
The control is inside a DataTemplate referenced by a Pivot (PivotHeaderTemplate). The default Foreground is the unselected status (semi-transparent SystemControlForegroundBaseMediumBrush) and should get the default "white" when selected (SystemControlHighlightAltBaseHighBrush).
The control Foreground property is applied by a template, and according to the live tree it's updating, but OnPropertyChanges is called only the first time.
For example, the Pivot has 2 views: the first one starts selected and is white, and the second is unselected and is "grayish".
If I change the selection, the view changes, the Foreground property changes accordingly on both controls but OnPropertyChanges is not called, and my canvas doesn't change (because the invalidation logic is inside that method).
[UPDATE: as a workaround, I used the event LayoutUpdated to check what changed.]
For a test project, create a new UWP XAML project a new MyCanvas UserControl.
MyCanvas.xaml:
<UserControl x:Class="InheritControlProperty.Controls.MyCanvas"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:InheritControlProperty.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Canvas x:Name="content" Width="50" Height="50"/>
</UserControl>
MyCanvas.xaml.cs
using System;
using Windows.UI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
namespace InheritControlProperty.Controls
{
public sealed partial class MyCanvas : UserControl
{
private Color Value
{
get { return (Foreground as SolidColorBrush)?.Color ?? Colors.Black; }
}
public MyCanvas()
{
InitializeComponent();
RegisterPropertyChangedCallback(ForegroundProperty, OnPropertyChanged);
}
private void OnPropertyChanged(DependencyObject sender, DependencyProperty dp)
{
content.Background = new SolidColorBrush(Value);
//Logic for more complex canvas management here
}
}
}
MainPage.xaml
<Page x:Class="InheritControlProperty.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:InheritControlProperty"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:cntr="using:InheritControlProperty.Controls"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Page.Resources>
<DataTemplate x:Key="NameTemplate">
<Grid BorderBrush="Orange" BorderThickness="2">
<cntr:MyCanvas Width="100" Height="50"/>
<!-- Try using Foreground="Red" -->
</Grid>
</DataTemplate>
</Page.Resources>
<Pivot Margin="20" HeaderTemplate="{StaticResource NameTemplate}">
<PivotItem>Item 1</PivotItem>
<PivotItem>Item 2</PivotItem>
</Pivot>
</Page>
I have a question concerning data binding with tabs.
I have the following xaml code:
<Window x:Class="SuperAtomsController.GUI.windowAnalog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="windowAnalog" Height="900" Width="1400"
DataContext="{Binding RelativeSource={RelativeSource self}}">
<Grid>
<TabControl Height="459" HorizontalAlignment="Left" Margin="188,278,0,0" Name="tabControl1" ItemsSource="{Binding Path=model.sequences}" VerticalAlignment="Top" Width="883">
</TabControl>
</Grid>
</Window>
And the code behind:
public partial class windowAnalog : Window
{
public Data model;
public windowAnalog(Data model)
{
this.model = model;
InitializeComponent();
}
}
But with this nothing appears in the tabcontrol (model.sequences is of the type ObservableCollection<>). If remove the itemssource in xaml and add the following in the c# code tabControl1.ItemsSource = model.sequences; after the InitializeComponent(); it works fine. What am I missing?
Clearly your binding isn't resolving, check your debug output window for helpful diagnostic messages.
I can't recall but I think model may need to be a property instead of a field for WPF property path to work. Otherwise maybe it was a problem with the DataContext. You coudl try doing this.DataContext = this to your constructor before InitializeComponent() instead of your DataContext xaml.