nepuan
nepuan

Reputation: 43

binding datacontext to usecontrol

I created my UserControl and in code behind I added the property CompanyName, FirstName and SecondName. I added DependencyProperty for each property. In xaml I use LongListSelector and I would like to bind in ItemTemplate some things from viewmodel: observable collection(FirstName and SecondName) and one string(CompanyName).

For some reason the DependencyProperty for CompanyName is not fired and the value is not binded. For ObservableCollection everything is binded.

NOTE: I dont want to bind the Text property of TextBlock. This is just new project, where I am trying to fix the problem. In real project I work with these properties in code behind and after that something happens.

I will give half of my kingdom and my daughter who solve this problem, cause I am facing this problem for few days.

Here is the example solution

Here is the code..

Code behind MyUserControl.cs

public partial class MyUserControl : UserControl
{
    public MyUserControl()
    {
        InitializeComponent();
        this.Loaded += MyUserControl_Loaded;
    }

    private void MyUserControl_Loaded(object sender, RoutedEventArgs e)
    {
        txtCompanyName.Text = CompanyName;
        txtFirstName.Text = FirstName;
        txtSecondName.Text = SecondName;
    }

    public string CompanyName
    {
        get
        {
            return (string)GetValue(CompanyNameProperty);
        }
        set
        {
            SetValue(CompanyNameProperty, value);
        }
    }

    public static DependencyProperty CompanyNameProperty = DependencyProperty.Register("CompanyName", typeof(string), typeof(MyUserControl), new PropertyMetadata("", CompanyNameChanged));

    private static void CompanyNameChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var sender = d as MyUserControl;
        if (sender == null) return;

        var newValue = e.NewValue as string;
        sender.CompanyName = newValue;
    }

    public string FirstName
    {
        get
        {
            return (string)GetValue(FirstNameProperty);
        }
        set
        {
            SetValue(FirstNameProperty, value);
        }
    }

    public static DependencyProperty FirstNameProperty = DependencyProperty.Register("FirstName", typeof(string), typeof(MyUserControl), new PropertyMetadata("", FirstNameChanged));

    private static void FirstNameChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var sender = d as MyUserControl;
        if (sender == null) return;

        var newValue = e.NewValue as string;
        sender.FirstName = newValue;
    }

    public string SecondName
    {
        get
        {
            return (string)GetValue(SecondNameProperty);
        }
        set
        {
            SetValue(SecondNameProperty, value);
        }
    }

    public static DependencyProperty SecondNameProperty = DependencyProperty.Register("SecondName", typeof(string), typeof(MyUserControl), new PropertyMetadata("", SecondNameChanged));

    private static void SecondNameChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var sender = d as MyUserControl;
        if (sender == null) return;

        var newValue = e.NewValue as string;
        sender.SecondName = newValue;
    }

}

MainPage.xaml

<phone:PhoneApplicationPage
x:Class="PhoneApp6.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
shell:SystemTray.IsVisible="True"
xmlns:sharecontrols="clr-namespace:PhoneApp6"
x:Name="self">

<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>



    <!--TitlePanel contains the name of the application and page title-->
    <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
        <TextBlock Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}" Margin="12,0"/>
        <TextBlock Text="page name" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
    </StackPanel>

    <!--ContentPanel - place additional content here-->
    <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
        <phone:LongListSelector 
            x:Name="MainLongListSelector" 
            Margin="0,0,-12,0" 
            ItemsSource="{Binding Employees}">
            <phone:LongListSelector.ItemTemplate>
                <DataTemplate>
                    <StackPanel Margin="0,0,0,17">
                        <sharecontrols:MyUserControl 
                            FirstName="{Binding FirstName}"
                            SecondName="{Binding SecondName}"
                            CompanyName="{Binding ElementName=self, Path=DataContext.CompanyName}"
                            />
                    </StackPanel>
                </DataTemplate>
            </phone:LongListSelector.ItemTemplate>
        </phone:LongListSelector>
    </Grid>
</Grid>

</phone:PhoneApplicationPage>

Upvotes: 0

Views: 95

Answers (1)

Alen Lee
Alen Lee

Reputation: 2509

I view your sample solution, check and motify your code, finally I achieve what you want, I found several problems.

  • The code CompanyName="{Binding ElementName=self, Path=DataContext.CompanyName}" in the page MainPage, you bind the CompanyName to self(the page), path to DataContext, but in the code behind LayoutRoot.DataContext = App.ViewModel;, so change the LayoutRoot to this

  • Change the property CompanyName as public property in the class MainViewModel

  • Add sender.txtCompanyName.Text = newValue in the method CompanyNameChanged in the class MyUserControl. Beause when the control is initalizing, the DataContext might uninitialized, so when you set the txtCompanyName.Text = CompanyName, the CompanyName is null. You must reset the txtCompanyName when the CompanyName property is changed.

The code:

sender.txtCompanyName.Text = newValue;

Wish this can help you. If help you please mark it as answer.

Upvotes: 1

Related Questions