Home > database >  Data Binding to User Control Error Data.Binding cannot be converted to System.String
Data Binding to User Control Error Data.Binding cannot be converted to System.String

Time:10-20

I'm new to WPF and I'm having trouble binding text to a user control I made. It's a simple control, it's just basically a button with text and a image that I want to reuse in several Views.

Here is my User Control's .cs

public partial class MenuItemUserControl : UserControl
{
    public string TextToDisplay { get; set; }

    public MenuItemUserControl()
    {
        InitializeComponent();
        DataContext = this;
    }
}

Here is my User Control's xaml

<UserControl x:Class="Class.Controls.MenuItemUserControl"
             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:local="clr-namespace:Class.Controls"
             mc:Ignorable="d" 
             d:DesignHeight="83.33" d:DesignWidth="512">
    <Grid>
        <Button Style="{StaticResource MenuItemStyle}" Height="Auto" Width="Auto">
            <DockPanel LastChildFill="True" Width="512" Height="83.33" HorizontalAlignment="Center" VerticalAlignment="Center">
                <Image Source="/Resources/MenuArrow.png" Stretch="None" HorizontalAlignment="Left" VerticalAlignment="Center" DockPanel.Dock="Left"/>
                <TextBlock d:Text="sample" Text="{Binding TextToDisplay, Mode=OneWay}" HorizontalAlignment="Left" VerticalAlignment="Center" FontSize="{StaticResource MenuItems}"/>
            </DockPanel>
        </Button>
    </Grid>
</UserControl>

Here is my View xaml

<Page x:Class="Class.Views.MenuOperate"
      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:uc="clr-namespace:Class.Controls"
      xmlns:local="clr-namespace:Class.Views"
      xmlns:properties="clr-namespace:Class.Properties"
      xmlns:mah="http://metro.mahapps.com/winfx/xaml/controls" xmlns:viewmodels="clr-namespace:Class.ViewModels" d:DataContext="{d:DesignInstance Type=viewmodels:MenuOperateViewModel}"
      mc:Ignorable="d" 
      d:DesignHeight="500" d:DesignWidth="1024"
      Title="MenuOperate">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="83.33"/>
            <RowDefinition Height="83.33"/>
            <RowDefinition Height="83.33"/>
            <RowDefinition Height="83.33"/>
            <RowDefinition Height="83.33"/>
            <RowDefinition Height="83.33"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="512"/>
            <ColumnDefinition Width="512"/>
        </Grid.ColumnDefinitions>
        
        <uc:MenuItemUserControl TextToDisplay="{Binding StartStop, Mode=TwoWay}" Grid.Row="0" Grid.Column="0"/>
        </Grid>
</Page>

Here is my View Model .cs

namespace Class.ViewModels
{
    public class MenuOperateViewModel : ObservableObject
    {
        private string? _StartStop;

        public MenuOperateViewModel()
        {
            StartStop = Properties.Resources.MenuOperateStart;
        }

        public string? StartStop
        {
            get => _StartStop;
            set => SetProperty(ref _StartStop, value);
        }
    }
}

This is the error I get in my View Xaml:

Object of Type 'System.Windows.Data.Binding' cannot be converted to type 'System.String'.

CodePudding user response:

There are two things that prevent that the expression

TextToDisplay="{Binding StartStop}"

works.

  1. The target property of the Binding, i.e. TextToDisplay must be a dependency property.

  2. You must not explicity set the UserControl's DataContext. The Binding will resolve the source property path relative to the current DataContext, i.e. with DataContext = this; in the control's constructor, it expects the source property StartStop on the UserControl, which is obviously wrong.

For details, see Data binding overview


Your code should look like this:

public partial class MenuItemUserControl : UserControl
{
    public static readonly DependencyProperty TextToDisplayProperty =
        DependencyProperty.Register(
            nameof(TextToDisplay),
            typeof(string),
            typeof(MenuItemUserControl));

    public string TextToDisplay
    {
        get { return (string)GetValue(TextToDisplayProperty); }
        set { SetValue(TextToDisplayProperty, value); }
    }

    public MenuItemUserControl()
    {
        InitializeComponent();
    }
}

The Binding in the UserControl's XAML would then use a RelativeSource Binding.

<TextBlock Text="{Binding TextToDisplay,
                  RelativeSource={RelativeSource AncestorType=UserControl}}" />
  • Related