Question

I would like to bind the IsEnabled property of TabItem to data within my code.

e.g. I have a TabItem defined as follows

<TabItem Name="Tab1" Header="Tab1" IsEnabled="{Binding Path=Tab1Enabled, Mode=TwoWay}">
</TabItem>

And I have defined a data class which inherits from INotifyPropertyChanged as follows

class MyData : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string name)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(name));
        }
    } 
    public bool Tab1Enabled
    {
        get{ return m_tab1Enabled; }
        set
        {
            m_tab1Enabled = value;
            OnPropertyChanged("Tab1Enabled");
        }
    }            
}

Then I set the DataContext to my data member.

public partial class MyApp : Window
{
    MyData m_myData = new MyData();
    MyApp()
    {
        InitializeComponent();
        this.DataContext = m_myData;
    }
}

However, when the Tab1Enabled property gets set programatically, the PropertyChanged event is null and so the notification event is not sent.

Thanks in advance.

Was it helpful?

Solution

Im guessing you need to change m_bindinData to the variable you want to bind to (m_myData). I fired up VS2012 and tested your code. Setting m_myData.Tab1Enabled = true; set the tab to enabled and setting m_myData.Tab1Enabled = false; disabled it correctly. Heres what I had.

public partial class MyApp : Window
{
    MyData m_myData = new MyData();
    MyApp()
    {
        this.DataContext = m_myData;
        InitializeComponent();

        m_myData.Tab1Enabled = true;
    }
}

class MyData : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string name)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(name));
        }
    }
    public bool Tab1Enabled
    {
        get { return m_tab1Enabled; }
        set
        {
            m_tab1Enabled = value;
            OnPropertyChanged("Tab1Enabled");
        }
    }

    private bool m_tab1Enabled;
}

<TabControl>
    <TabItem Name="Tab1" Header="Tab1" IsEnabled="{Binding Path=Tab1Enabled}">
    </TabItem>
    <TabItem Name="Tab2" Header="Tab2">
    </TabItem>
</TabControl>

OTHER TIPS

What about this? Notice the PropertyChangedEventHandler PropertyChanged = PropertyChanged; line in the OnPropertyChanged method.

class MyData : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string name)
    {
        PropertyChangedEventHandler PropertyChanged = PropertyChanged;
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(name));
        }
    } 
    public bool Tab1Enabled
    {
        get{ return m_tab1Enabled; }
        set
        {
            m_tab1Enabled = value;
            OnPropertyChanged("Tab1Enabled");
        }
    }            
}

Your TabItem might not inheriting DataContext of your Window. Try looking into the output window, binding failure error will be there.

As a workaround you can use RelativeSource to travel upto the DataContext of your window and bind with its related property like this -

<TabItem Name="Tab1" Header="Tab1"
         IsEnabled="{Binding Path=DataContext.Tab1Enabled,
                            RelativeSource={RelativeSource Mode=FindAncestor,
                                   AncestorType=Window}, Mode=TwoWay}"/>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top