Issue in using Binding with ElementName in Data Template which is passed through DependencyProperty

guess_me_if_u_can 126 Reputation points
2020-03-08T08:08:41.69+00:00

In my case, i have a control named MultiSelectListView.xaml which holds the dataTemplate

        <DataTemplate x:Key=&#34;ListTemplate&#34; x:DataType=&#34;model:BaseMultiSelectModel&#34;>  
            <Grid Margin=&#34;32,0,20,0&#34; BorderThickness=&#34;0,0,0,1&#34; BorderBrush=&#34;{ThemeResource SystemControlBackgroundChromeMediumBrush}&#34; Background=&#34;Transparent&#34;>  
                <Grid Margin=&#34;0,12,0,12&#34;>  
                    <Grid.ColumnDefinitions>  
                        <ColumnDefinition Width=&#34;Auto&#34;/>  
                        <ColumnDefinition Width=&#34;*&#34;/>  
                    </Grid.ColumnDefinitions>  
                    <CheckBox IsChecked=&#34;{x:Bind IsChecked, Mode=TwoWay}&#34; MinWidth=&#34;0&#34;/>  
                    <ContentControl Grid.Column=&#34;1&#34; HorizontalAlignment=&#34;Stretch&#34; Content=&#34;{Binding}&#34; ContentTemplate=&#34;{Binding ListTemplate, ElementName=MultiSelectList, Mode=OneWay}&#34;/>  
                </Grid>  
            </Grid>  
        </DataTemplate>  

I have a Dependency Property in MultiSelectListView.xaml.cs named ListTemplate which holds the rest of the DataTemplate which i displayed through ContentControl inside DataTemplate.

In my UserView.xaml

    <controls:MultiSelectListView IsLoading=&#34;{x:Bind ProjectUserModel.IsLoading, Mode=OneWay}&#34;  
                                  IsSelectallChecked=&#34;{x:Bind ProjectUserModel.IsSelectallChecked, Mode=TwoWay}&#34;  
                                  ItemsSource=&#34;{x:Bind ProjectUserModel.ItemsList, Mode=OneWay}&#34;>  
        <controls:MultiSelectListView.ListTemplate>  
            <DataTemplate x:DataType=&#34;model:UserModel&#34;>  
                <Grid>  
                    <Grid.ColumnDefinitions>  
                        <ColumnDefinition Width=&#34;300&#34;/>  
                        <ColumnDefinition Width=&#34;{Binding IsColumn2Visible, ElementName=UserView, Mode=OneWay}&#34;/>  
                        <ColumnDefinition Width=&#34;{Binding IsColumn3Visible, ElementName=UserView, Mode=OneWay}&#34;/>  
                    </Grid.ColumnDefinitions>  
                    <StackPanel Grid.Column=&#34;0&#34; Margin=&#34;10,0,0,0&#34;>  
                        <TextBlock Text=&#34;{x:Bind name, Mode=OneWay}&#34; Style=&#34;{StaticResource TextBlockStyle}&#34;/>  
                        <TextBlock Foreground=&#34;{StaticResource SystemControlForegroundBaseMediumBrush}&#34; Margin=&#34;0,5,0,0&#34; Text=&#34;{x:Bind email, Mode=OneWay}&#34; Style=&#34;{StaticResource TextBlockStyle}&#34;/>  
                    </StackPanel>  
                    <TextBox Grid.Column=&#34;1&#34; VerticalAlignment=&#34;Center&#34; Margin=&#34;5,0,25,0&#34; Text=&#34;{x:Bind value2, Mode=TwoWay}&#34; BorderThickness=&#34;1&#34;/>  
                    <TextBox Grid.Column=&#34;2&#34; VerticalAlignment=&#34;Center&#34; Margin=&#34;5,0,25,0&#34; Text=&#34;{x:Bind value3, Mode=TwoWay}&#34; BorderThickness=&#34;1&#34;/>  
                </Grid>  
            </DataTemplate>  
        </controls:MultiSelectListView.ListTemplate>  
    </controls:MultiSelectListView>  

In UserView.xaml, x:Bind is working fine. but for binding the column visibility the value will not be available in UserModel. Hence used Binding to fetch from the UserView.xaml.cs. As i used DataTemplate, The Template directly applies to the MultiSelectListView's ContentControl and trying to obtain the IsColumn2Visible, IsColumn3Visible which will not be available there.

My Question is how do i bind the Column visiblity with IsColumn2Visible, ISColumn3Visible ? Please don't prefer individual DependencyProperty on MultiSelectListView.xaml for all Visiblity property, hence the binding ListTemplate is dynamic.

Universal Windows Platform (UWP)
{count} votes

Accepted answer
  1. Fay Wang - MSFT 5,191 Reputation points
    2020-03-12T09:38:54.3+00:00

    Hello,

    ​Welcome to our Microsoft Q&A platform!

    By checking your code, the reason why IsColumn2Visible and IsColumn3Visible can't work is because your binding targets are in a data template or control template, then its XAML namescope is the XAML namescope of the templated parent. So the XAML namescope of your binding targets is actually MultiSelectListView which named MultiSelectList instead of your UserView. When you set ElementName as UserView, it can't find. So you need to set the ElementName as MultiSelectList.

    Update:

    Since you can find the 'MultiSelectList' ElementName, so you can set its DataContext as UserView and use DataContext.Column2Width to bind with Width. For example:

    UserView:

    <local:MultiSelectListView ItemsSource="{x:Bind Users, Mode=OneWay}">
            <local:MultiSelectListView.ListTemplate>
                <DataTemplate x:DataType="model:UserModel">
                    <Grid Margin="32,0,20,0" Background="Transparent">
                        <Grid Margin="0,12,0,12">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="100"></ColumnDefinition>
                                <ColumnDefinition Width="{Binding DataContext.Column2Width, ElementName=MultiSelectList, Mode=OneWay}"/>
                                <ColumnDefinition Width="{Binding DataContext.Column3Width, ElementName=MultiSelectList, Mode=OneWay}"/>
                            </Grid.ColumnDefinitions>
                            <TextBlock Text="Hello"/>
                            <TextBlock Grid.Column="1" VerticalAlignment="Center" Margin="5,0,25,0" Text="Column2"/>
                            <TextBlock Grid.Column="2" VerticalAlignment="Center" Margin="5,0,25,0" Text="Column3"/>
                        </Grid>
                    </Grid>
                </DataTemplate>
            </local:MultiSelectListView.ListTemplate>
        </local:MultiSelectListView>
    

    UserView.xaml.cs:

    public MainPage()
    {
        this.InitializeComponent();
    
        Users.Add(new UserModel());
        Users.Add(new UserModel());
    
        //Set current DataContext as current page
        this.DataContext = this;
    }
    

0 additional answers

Sort by: Most helpful