this code work correct:
<UserControl x:Class="Extended.InputControls.TextBoxUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Extended.InputControls">
<TextBox x:Name="textBox"
ToolTip="{Binding Path=CustomToolTip,RelativeSource={RelativeSource AncestorType=local:TextBoxUserControl}}"/>
</UserControl>
but this code Does not work!!!
<UserControl x:Class="Extended.InputControls.TextBoxUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Extended.InputControls">
<TextBox x:Name="textBox">
<TextBox.ToolTip>
<ToolTip Text="{Binding Path=CustomToolTip,RelativeSource={RelativeSource AncestorType=local:TextBoxUserControl}}" Background="Yellow"/>
</TextBox.ToolTip>
</TextBox>
</UserControl>
i need create custom tooltip and bind it to CustomToolTip but in second code that's not bind to anything
where is the problem?
First of all, if we're talking WPF here, it should be <ToolTip Content="..."> instead of <ToolTip Text="...">, since ToolTip has no Text property.
Regarding the binding: Binding to other elements in the user control from within a ToolTip doesn't work since ToolTip elements are not part of the visual tree, as explained in another question that also provides one potential solution.
However, it seems that you're binding to some property defined in the UserControl's code-behind? In that case it's even easier to solve by setting the UserControl's DataContext to the control itself:
<UserControl x:Class="Extended.InputControls.TextBoxUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Extended.InputControls"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<TextBox x:Name="textBox">
<TextBox.ToolTip>
<ToolTip Content="{Binding CustomToolTip}" Background="Yellow"/>
</TextBox.ToolTip>
</TextBox>
</UserControl>
Alternatively, you could also set the DataContext in code-behind:
public TextBoxUserControl()
{
this.DataContext = this;
InitializeComponent();
}
In both cases, the CustomToolTip property can be accessed directly without the need for a RelativeSource binding.
An even better solution would be to introduce come kind of Viewmodel class that holds the CustomToolTip and all similar properties, and set this class as the UserControl's DataContext.
Related
I am creating a custom panel which is basically just a fancier StackPanel with some added functionality. I was going to use a UserControl which contains a StackPanel but I don't know how to make my UserControl accept content to fill it's StackPanel.
This is what I'm trying:
<UserControl
x:Class="transformations.fold_panel"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:transformations"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<StackPanel Orientation="Vertical">
<Button Content="First" />
<ContentControl Content="{x:Bind Content, Mode=OneWay}"></ContentControl>
</StackPanel>
</UserControl>
Usage:
<local:fold_panel>
<Button Content="Second" />
</local:fold_panel>
When I try this I get the following error:
WinRT originate error - 0x80070057 : 'The parameter is incorrect.'.
You can't bind the Content of a StackPanel in a UserControl's Content to the Content property of the same UserControl. This will introduce a circular reference.
In your example, the Content property of the fold_panel UserControl will be set to the StackPanel that you defined in the XAML markup.
If you want to be able to set the Content of the ContentControl in the StackPanel, you should add a custom dependency property to the fold_panel class and bind the Content property of the ContentControl to this one:
<ContentControl Content="{x:Bind CustomContent, Mode=OneWay}" />
You can then set your custom property something like this:
<local:fold_panel>
<local:fold_panel.CustomContent>
<Button Content="Second" />
<local:fold_panel.CustomContent>
</local:fold_panel>
But if you really want a custom StackPanel, you should create a class that inherits from StackPanel rather than UserControl.
I tried this simple example from the official Xamarin page, that contains a template binding like:
<ControlTemplate x:Key="TealTemplate">
<Grid>
<Label Text="{TemplateBinding Parent.HeaderText}" />
<Label Text="{TemplateBinding Parent.FooterText}" />
</Grid>
</ControlTemplate>
However, i always get ths error by just copying the example code to Visual Studio.:
Can anyone give me a short example how to bind from within a ControlTemplate to a property of the templated control, be it of the binding context or the control itself?
I haven't worked out the issue with 'Parent'. But for my project I use:
{TemplateBinding BindingContext.IsBusy}
IN the page that use ControlTemplate, I also use a ViewModel and binding this ViewModel, which has IsBusy property, to the page.
I want to create some components and reuse them in different pages, put more than one in a page, etc.
For example, I want to create a component that contains an image, some text, etc. The position of the elements are fixed, but I will change the image, the text... I mean, in a same page I want to put three circles with different image and text...
What is the best way to do it? I've found UserControl, but I'm unable to call a method from another page to change something.
This is my component XAML
<UserControl
x:Class="aa.Components.CircularGraph"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Components"
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="300">
<Grid Name="view">
<Image Name="imageGraph" Source="../Assets/aa/circuloGris.png"
/>
<StackPanel Orientation="Vertical">
<TextBlock Name="firstLine" Text="1" FontFamily="Arial" FontSize="9"></TextBlock>
<TextBlock Name="secondLine" Text="2" FontFamily="Arial" FontSize="9"></TextBlock>
<TextBlock Name="thirdLine" Text="3" FontFamily="Arial" FontSize="9"></TextBlock>
</StackPanel>
</Grid>
</UserControl>
Its code:
public sealed partial class CircularGraph: UserControl {
public CircularGraph() {
this.InitializeComponent();
Height = 300;
Width = 400;
}
public void changeFirstLine(string var) {
firstLine.Text = var;
}
}
In other page I put:
<local:CircularGraph Name="circularGraph"/>
And I've tried to put this in .cs:
protected override void OnNavigatedTo(NavigationEventArgs e) {
circularGraph.changeFirstLine("aaa");
}
But I have an error: The name 'circularGraph' does not exits in the current context.
How can I do this?
Sorry if it's a simple question. I'm newbie at Windows phone.
Thank you very much!
Try x:Name instead of Name. "All x:Name means to XAML is generate a field to store the value in the code behind class."
<local:CircularGraph x:Name="circularGraph"/>
In WPF, what are the differences between the x:Name and Name attributes?
I'm attempting to use EventToCommand to initialize my ViewModel, but the command isn't firing. I suspect it's because the Triggers section is not within the databound container, but how can I do that in my example? I'm trying to stick to straight XAML if possible.
<Window x:Class="MVVMSample.Home"
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"
xmlns:viewModels="clr-namespace:MVVMSample.ViewModels"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WPF4"
d:DataContext="{d:DesignInstance Type=viewModels:HomeViewModel, IsDesignTimeCreatable=True}"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<viewModels:HomeViewModel x:Key="ViewModel" x:Name="ViewModel" />
</Window.Resources>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Loaded">
<cmd:EventToCommand Command="{Binding LoadedCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<Grid DataContext="{StaticResource ViewModel}">
<TextBlock Text="{Binding PersonCount}" />
</Grid>
</Window>
You are right, the datacontext is part of the problem,but I would solve it by using mvvm-light as it was designed.
If you are using MVVM_Light then your should use the view model locator. Its the main backbone of the framework. I used mvvm light to learn about the mvvm principle. I liked it a lot because it was simple and allowed me to learn with as quick a learning curve as possible.
In mvvm-light you declare your viewmodellocator in your app.xaml
<Application.Resources>
<ResourceDictionary>
<!--Global View Model Locator-->
<vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" />
</ResourceDictionary>
</Application.Resources>
then in your view (be it a usercontrol or window etc) you "attach" you viewmodel to your view as follows: Notice the DataContext declaration.
<UserControl x:Class="FTC.View.TrackingListView"
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"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:cmd="http://www.galasoft.ch/mvvmlight"
mc:Ignorable="d"
DataContext="{Binding YourViewModel, Source={StaticResource Locator}}"
d:DesignHeight="700" d:DesignWidth="1000">
This way the view model locator from mvvm light can either create a singleton of your viewmodel or a unique instance as you need. It can also use IOC to inject services into the constructor of your viewmodel.
So for example, if I have a viewmodel that deals with people objects from a datamodel, i create a people service that performs the CRUD operation and then reference it in the viewmodel constructor parameters. This allows me to use either fake design time data or real data from the model. It also keep all concerns decoupled, which is the purpose of mvvm.
I recommend reading more about the MVVM-light framwork and building one of the samples from thier site a galasoft.
See this video
hope this helps
I have a ContentControl where I want to load the page myPage2. My XAML Codefrom this page looks like this:
<Page x:Class="ExampleApp.myPage2">
<Grid x:Name="Content" Height="651" Width="941" Background="White">
...
...
</Grid>
</Page>
I know that I can load a resource from a page with this Code:
protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
{
var contentControl = (ContentControl)container;
return (DataTemplate) contentControl.Resources[templateKey];
}
My problem now is that I can't load a page like above with this code. I have to write this:
<Page x:Class="ExampleApp.myPage2">
<Page.Resources>
<DataTemplate x:Key="Test">
<Grid x:Name="Content" Height="651" Width="941" Background="White">
...
...
</Grid>
</DataTemplate>
</Page.Resources>
</Page>
And then I can load the page with the same Code from above with templateKey="Test". But the main problem is that I want to use the first declaration of the page and do not want to use <Page.Resources> <DataTemplate x:Key="Test"> and so on. I want to load the site direcly from the first declaration (first code in this post). How can I create a DataTemplate directly from a page? Or is there an other way to load a page into a ContentControl?
There is no reason to use a Page within a ContentControl. A Page is a subclass of the UserControl class that adds support for being used within a Frame control to support navigation, back stack/history, etc. You should probably replace Page with UserControl in XAML and code behind, so you would end up with something like this:
<UserControl x:Class="ExampleApp.myControl2">
<Grid x:Name="Content" Height="651" Width="941" Background="White">
...
...
</Grid>
</UserControl>
You can put the UserControl itself in a DataTemplate if you want to use it as a DataTemplate in a ContentControl:
<ContentControl
xmlns:controls="using:ExampleApp">
<ContentControl.Resources>
<DataTemplate
x:Key="Test">
<controls:myControl2 />
</DataTemplate>
</ContentControl.Resources>
</ContentControl>