Search code examples
wpfxamlbindingdatatemplate

Binding properties to DataTemplate


I'm using a DataTemplate which is inside a ResourceDictionary file.

<DataTemplate x:Key="AlertWarningMessage">
    <Grid>
        <Border Visibility="{Binding DataContext.Visibility}" Background="{StaticResource ResourceKey=AlertWarningMessageBackground}" HorizontalAlignment="Stretch" Height="30">
            <WrapPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
                <TextBlock Text="WARNING !" FontWeight="Bold" Foreground="{StaticResource ResourceKey=AlertWarningMessageForeground}" FontSize="13"/>
                <TextBlock Text="{Binding DataContext.Message}" Foreground="{StaticResource ResourceKey=AlertWarningMessageForeground}" Margin="5,0,0,0"/>
            </WrapPanel>
        </Border>
    </Grid>
</DataTemplate>

I merge this dictionnary in my UserControl, and i'm using this template like this :

<ContentControl ContentTemplate="{StaticResource AlertWarningMessage}" Grid.Row="2" Margin="0,2,0,0" DataContext="{Binding AlertSummary, UpdateSourceTrigger=PropertyChanged}" />

In my VM, i'm using a class which have 2 properties :

    Public Class AlertInfos
        Public Property Visibility As Visibility
        Public Property Message As String

        Public Sub New(p_visibility As Visibility, p_msg As String)
            Me.Visibility = p_visibility
            Me.Message = p_msg
        End Sub
    End Class

Property VM as my class :

    Private _alertSummary As AlertInfos
    Public Property AlertSummary() As AlertInfos
        Get
            Return _alertSummary
        End Get
        Set(ByVal value As AlertInfos)
            _alertSummary = value
            RaisePropertyChanged("AlertSummary")
        End Set
    End Property

Properties of this object are set to Collapsed and String.Empty

Next, I change the values of this object, like this :

    Public Sub ShowAlert()
        Me.AlertSummary.Message = "Test"
        Me.AlertSummary.Visibility = Visibility.Visible
        'Me.StartTimerAlert()
        RaisePropertyChanged("AlertSummary")
    End Sub

But it's not working. There are 2 problems :

  • At the begining, when the Visibility is set to Collapsed, the Border is visible.
  • When I change the Message property, it is not visually updated.

I think there is a problem with my Binding, but I don't know where. I tried differents things, but there is always these problems. Furthermore, I had bind the property directly in a TextBlock below the ContentControl, and the Binding working find.

Do you have any idea ?


Solution

  • You should change your data template to this:

     <DataTemplate x:Key="AlertWarningMessage">
            <Grid>
                <Border Visibility="{Binding RelativeSource={RelativeSource AncestorType=ContentControl}, Path=DataContext.Visibility}" Background="AliceBlue" HorizontalAlignment="Stretch" Height="30">
                    <WrapPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
                        <TextBlock Text="WARNING !" FontWeight="Bold" Foreground="Red" FontSize="13"/>
                        <TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType=ContentControl}, Path=DataContext.Message}" Foreground="Red" Margin="5,0,0,0"/>
                    </WrapPanel>
                </Border>
            </Grid>
        </DataTemplate>
    

    And your AlertInfos to this (it's on C# so try to translate it to VB)

    public class AlertInfos
    {
        private string message;
    
        public string Message
        {
            get
            {
                return this.message;
            }
            set
            {
                if (this.message != value)
                {
                    this.message = value;
                }
            }
        }
        private Visibility visibility;
    
        public Visibility Visibility
        {
            get
            {
                return this.visibility;
            }
            set
            {
                if (this.visibility != value)
                {
                    this.visibility = value;
                }
            }
        }
    }
    

    It should work, at least it's working on my PC