user3060854
user3060854

Reputation: 933

Object created in XAML can't be called by x:Name in cs

The following code represents a simple project in which I am trying to call objects created in XAML. So, I call them by x:Name. In the test UI I created a grid with three rows. The second and third row are being populated directly by Label2 and Label3, but the first row is populated indirectly, via Window.Resources.

The problem is that myLabel2 and myLabel3 are recognizable in MainWindow.xaml.cs (the AutoComplete works for them), but for myLabel1 I receive en error message:

The name 'myLabel1' does not exist in the current project

So, I guess that to problem derives from the fact that myLabel1 was created inside Window.Resources.

Any thoughts would be appreciated.

This is the MainWindow.xaml code:

 <Window x:Class="test2.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:test2"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">

    <Window.Resources>
        <DataTemplate x:Key="something">
            <Label x:Name="myLabel1" Content="Labe1"/>
        </DataTemplate>
    </Window.Resources>

        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="*"/>
                <RowDefinition Height="*"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <ContentPresenter Grid.Row="0" ContentTemplate="{StaticResource something}" />
            <Label x:Name="myLabel2" Content="Labe2" Grid.Row="1" />
            <Label x:Name="myLabel3" Content="Labe3" Grid.Row="2" />
        </Grid>

</Window>

This is the MainWindow.xaml.cs code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace test2
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            myLabel2.Content = "new content myLabel2";
            myLabel3.Content = "new content myLabel3";
            myLabel1.Content = "new content myLabel1";
        }
    }
}

EDIT: Could I possibly use in .cs something like this.Resources["something"] ?

That was loosely adaptive from How to define and use resources in xaml so they can be used in C#

Upvotes: 0

Views: 1299

Answers (1)

foosburger
foosburger

Reputation: 359

As one of the commenters mentioned, the contents of your DataTemplate don't exist until ContentPresenter instantiates it for a data object.

Since myLabel1 is inside a DataTemplate, you presumably would want your Label's content to be based on whatever data object you are displaying in your ContentPresenter.

You didn't say anything about your data object, so let's say that data is an instance of a class called Widget:

public class Widget
{
    public string Title { get; set; }
}

Now the code that instantiates your data object (an instance of Widget) can set the value of the Title property. For example:

public MainWindow()
{
    InitializeComponent();
    myLabel2.Content = "new content myLabel2";
    myLabel3.Content = "new content myLabel3";

    Widget widgetItem = new Widget();
    widgetItem.Title = "new content myLabel1";

    // You could set this elsewhere, but I'm doing it here to simplify this example.
    myContentPresenter.Content = widgetItem;
}

Note that I gave your ContentPresenter a name so I could assign its Content for the sake of this example:

<ContentPresenter x:Name="myContentPresenter" Grid.Row="0" ContentTemplate="{StaticResource something}" />

Then in your XAML, bind your Label's Content property to the data object's Title property:

<Window.Resources>
    <DataTemplate x:Key="something">
        <Label x:Name="myLabel1" Content="{Binding Title}"/>
    </DataTemplate>
</Window.Resources>

If you want to be able to change the value of widgetItem.Title after the initial binding and see that change reflect in the UI, then your data object's class (Widget in this case) will need to implement INotifyPropertyChanged or inherit DependencyObject. I will leave it up to you to investigate that independently.

Upvotes: 1

Related Questions