Jez Avila
Jez Avila

Reputation: 51

WPF Binding two levels of UserControl

let's explain a little bit my issue, i wrote a code of an application that show a usercontrol with bindings that i'm trying to set to another sub-usercontrol. I'm using a model that i've set to my MainWindow.xaml.

THE PROBLEM IS:

The usercontrol innerusercontrol doesn't show changes in the bindings. I guess i made a mistake, but i don't know where and how to fix it. I read several posts but no body answer them with a specific code-line. Could any body help me?

I'll appreciate an answer. Thanks

MainWindow.xaml

<Window x:Class="DependencyProperties.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:DependencyProperties"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition Height="3*"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <local:DisplayProduct x:Name="ucDisplay" Grid.Row="1" Height="110"/>
        <Button Grid.Row="2" Click="Button_Click">Apply circle visibility false/true</Button>
    </Grid>
</Window>

MainWindow.xaml.cs

public partial class MainWindow : Window
    {
        public static ProductModel product;
        public MainWindow()
        {
            InitializeComponent();
            product = new ProductModel() { IsActivo = true, Descuento = 15.00, Importe = 100.00, Total = 85.00 };
            ucDisplay.DataContext = product;
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            Console.WriteLine("Antes " + product.IsActivo);
            product.IsActivo = !product.IsActivo;
            Console.WriteLine("Despues" + product.IsActivo);
        }
    }

DisplayProductUserControl.xaml

<UserControl x:Class="DependencyProperties.DisplayProductUserControl"
             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:DependencyProperties"
             mc:Ignorable="d" x:Name="win_Display"
             d:DesignHeight="80" d:DesignWidth="500">
    <UserControl.Resources>
        <Style TargetType="TextBlock">
            <Setter Property="FontSize" Value="18"/>
            <Setter Property="FontWeight" Value="Light"/>
        </Style>
    </UserControl.Resources>
    <Grid>
        <Viewbox>
            <Grid Width="{Binding ElementName=win_Display, Path=ActualWidth}" Height="{Binding ElementName=win_Display, Path=ActualHeight}">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition />
                    <ColumnDefinition />
                    <ColumnDefinition />
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition />
                    <RowDefinition />
                </Grid.RowDefinitions>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="Price: "/>
                    <TextBlock Text="$"/>
                    <TextBlock Text="{Binding Path=Price}"/>
                </StackPanel>
                <StackPanel Grid.Column="1" Orientation="Horizontal">
                    <TextBlock Text="Discount: "/>
                    <TextBlock Text="$"/>
                    <TextBlock Text="{Binding Path=Discount}"/>
                </StackPanel>
                <StackPanel Grid.Column="2" Orientation="Horizontal">
                    <TextBlock Text="Total: "/>
                    <TextBlock Text="$"/>
                    <TextBlock Text="{Binding Path=Total}"/>
                </StackPanel>
                <local:InnerUserControl Grid.Column="0" Grid.Row="1">
                    <local:InnerUserControl DataContext="{Binding Path=IsActive,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UserControl}}"/>
                </local:InnerUserControl>
            </Grid>
        </Viewbox>
    </Grid>
</UserControl>

InnerUserControl *THE PROBLEM IS HERE <------------------ *

    <UserControl x:Class="DependencyProperties.InnerUserControl"
                 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" 
                 mc:Ignorable="d"  x:Name="win_inner"
                 d:DesignHeight="40" d:DesignWidth="100">
        <UserControl.Resources>
            <BooleanToVisibilityConverter x:Key="VisibilityConverter"/>
        </UserControl.Resources>
        <Grid Width="{Binding ElementName=win_inner, Path=ActualWidth}">        
                <TextBlock Text="{Binding Path=IsActive}" FontSize="15"/>
**<!-- HERE IS THE PROBLEM I DOESN'T SHOW CHANGES WHEN IsActive is false/true -->**
                <Ellipse Height="{Binding ElementName=win_inner, Path=ActualHeight}" Width="{Binding RelativeSource={RelativeSource Self}, Path=ActualHeight}" Fill="Red"
                         Visibility="{Binding Path=IsActive, Converter={StaticResource VisibilityConverter}}" HorizontalAlignment="Right"></Ellipse>
        </Grid>
    </UserControl>

ProductoModel

public class ProductModel : INotifyPropertyChanged
{
    private double price;

    public double Price
    {
        get { return price; }
        set { price= value; }
    }

    private double discount;

    public double Discount
    {
        get { return discount; }
        set { discount= value; }
    }

    private double total;

    public double Total
    {
        get { return total; }
        set { total = value; }
    }

    private bool isActive;

    public bool IsActive
    {
        get { return isActive; }
        set { isActive = value; }
    }


    protected void RaisePropertyChanged(string propertyName)
    {
        var handler = PropertyChanged;

        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

Upvotes: 1

Views: 197

Answers (1)

JasonRho
JasonRho

Reputation: 106

like dnr3 commented already,

Add RaisePropertyChanged method in your 'Product Model' class.

public bool IsActive
{
    get { return isActive; }
    set 
    { 
        isActive = value; 
        RaisePropertyChanged("IsActive");
    }
}

View never changes until it gets 'PropertyChanged' Event.

Upvotes: 1

Related Questions