question

SherryShi-6041 avatar image
0 Votes"
SherryShi-6041 asked SherryShi-6041 commented

Problem with TabControl Template and Binding in WPF.

I would like to put image in TabControl header using binding, but below code doesn't work. I would like to know why, and how to do it? Thanks in advance :)

1、MainWindow.xaml

 <Window x:Class="WpfApp3.MainWindow"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
         mc:Ignorable="d"
         Title="MainWindow" Height="450" Width="800">
     <Grid>
         <TabControl Height="300" ItemsSource="{Binding TabCollection}">
             <!-- this is the header template-->
             <TabControl.ItemTemplate>
                 <DataTemplate>
                     <StackPanel>
                         <Label Content="{Binding Path=DisplayIndex}" />
                         <Image Source="{Binding Path=ContentObject.BackgroundImageSource}" Width="50"></Image>
                     </StackPanel>
                 </DataTemplate>
             </TabControl.ItemTemplate>
             <!-- this is the body of the TabItem template-->
             <TabControl.ContentTemplate>
                 <DataTemplate>
                     <TextBlock Text="{Binding Path=ContentObject.ShowContent}" />
                 </DataTemplate>
             </TabControl.ContentTemplate>
         </TabControl>
         <Button Content="Button" HorizontalAlignment="Left" Margin="273,391,0,0" VerticalAlignment="Top" Click="Button_Click"/>
     </Grid>
 </Window>


2、MainWindow.xaml.cs

  public partial class MainWindow : Window
     {
         public MainWindow()
         {
             vm = new WindowVM();
             this.DataContext = vm;
             InitializeComponent();
         }
    
         private WindowVM vm;
    
         private void Button_Click(object sender, RoutedEventArgs e)
         {
             vm.Init();
         }
     }


3、WindowVM

  public class WindowVM : INotifyPropertyChanged
     {
         #region Fields & Properties
    
         public event PropertyChangedEventHandler PropertyChanged;
    
         public ObservableCollection<ITestView> TabCollection { get; } = new ObservableCollection<ITestView>();
    
         #endregion
    
         public void Init()
         {
             List<ITestView> list = new List<ITestView>()
             {
                 new Test1View(),
                 // new Test2View()...
             };
    
             foreach (ITestView test in list)
             {
                 TabCollection.Add(test);
             }
         }
     }

4、Interface

  public interface ITestView
     {
         IContentTest ContentObject { get; set; }
         int DisplayIndex { get; set; }
     }
    
     public interface IContentTest
     {
         string ShowContent { get; set; }
         ImageSource BackgroundImageSource { get; set; }
     }


5、Test1View.xaml & Test1View.xaml.cs & ContentTest1

 <UserControl x:Class="WpfApp3.Test1View"
              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:WpfApp3"
              mc:Ignorable="d" 
              d:DesignHeight="450" d:DesignWidth="800">
     <Grid>
                
     </Grid>
 </UserControl>
    
    
 public partial class Test1View : UserControl,ITestView
     {
         public Test1View()
         {
             InitializeComponent();
         }
    
         #region ITestView Members
    
         public IContentTest ContentObject { get; set; } = new ContentTest1();
    
         public int DisplayIndex { get; set; } = 1;
    
         #endregion
    
     }
    
    
  public class ContentTest1 : IContentTest, INotifyPropertyChanged
     {
         public ContentTest1()
         {
             ShowContent = "TestAAA";
    
             // in ResourceDictionary: <ImageSource x:Key="Image111">aaa.png</ImageSource>
             BackgroundImageSource = Application.Current.TryFindResource("Image111") as ImageSource;
         }
    
         #region IContentTest Members
    
         private string _showContent;
         public string ShowContent
         {
             get => _showContent;
             set
             {
                 _showContent = value;
                 PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ShowContent)));
             }
         }
    
         private ImageSource _backgroundImageSource;
         public ImageSource BackgroundImageSource
         {
             get => _backgroundImageSource;
             set
             {
                 _backgroundImageSource = value;
                 PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(BackgroundImageSource)));
             }
         }
    
         #endregion
    
         #region INotifyPropertyChanged Members
    
         public event PropertyChangedEventHandler PropertyChanged;
    
         #endregion
    
     }
















windows-wpfdotnet-wpf-xaml
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

1 Answer

HuiLiu-MSFT avatar image
0 Votes"
HuiLiu-MSFT answered SherryShi-6041 commented

If you want to achieve the following effect, you can refer to its code. If I misunderstood, please let me know.
MainWinow.xaml:

  <Grid>
         <TabControl Height="300" ItemsSource="{Binding TabCollection}">
             <TabControl.ItemTemplate>
                 <DataTemplate>
                     <StackPanel>
                         <Label Content="{Binding MyHeader}" />
                         <Image Source="{Binding ImageHeader}" Width="50"></Image>
                     </StackPanel>
                 </DataTemplate>
             </TabControl.ItemTemplate>
             <TabControl.ContentTemplate>
                 <DataTemplate>
                     <TextBlock Text="{Binding MyContents}" />
                 </DataTemplate>
             </TabControl.ContentTemplate>
         </TabControl>
         <Button Content="Button" HorizontalAlignment="Left" Margin="273,391,0,0" VerticalAlignment="Top" Click="Button_Click"/>
     </Grid>

MainWindow.xaml.cs:

 using System;
 using System.Collections.Generic;
 using System.Collections.ObjectModel;
 using System.ComponentModel;
 using System.Runtime.CompilerServices;
 using System.Windows;
 using System.Windows.Media.Imaging;
    
 namespace TabControlDemo
 {
   public partial class MainWindow : Window
   {
     public MainWindow()
     {
       vm = new WindowVM();
       this.DataContext = vm;
       InitializeComponent();
     }
     private WindowVM vm;
    
     private void Button_Click(object sender, RoutedEventArgs e)
     {
       vm.Init();
     }
   }
   public class WindowVM : INotifyPropertyChanged
   {
        
     public ObservableCollection<MyContent> TabCollection { get; } = new ObservableCollection<MyContent>();
    
     public void Init()
     {
       List<MyContent> list = new List<MyContent>();
       list.Add(new MyContent(){ MyHeader="Tab 1" , ImageHeader= new BitmapImage(new Uri("spring.jpg", UriKind.Relative)), MyContents="Content 1" });
       list.Add(new MyContent(){ MyHeader="Tab 2" , ImageHeader= new BitmapImage(new Uri("images.jpg", UriKind.Relative)), MyContents="Content 2" });
       list.Add(new MyContent(){ MyHeader="Tab 3" , ImageHeader= new BitmapImage(new Uri("spring1.jpg", UriKind.Relative)), MyContents="Content 3" });
    
       foreach (MyContent test in list)
       {
         TabCollection.Add(test);
       }
     }
     public event PropertyChangedEventHandler PropertyChanged;
   }
   public class MyContent : INotifyPropertyChanged
      
   {
     public string myHeader;
     public string MyHeader
     {
       get { return myHeader; }
       set
       {
         myHeader = value;
         OnPropertyChanged();
       }
     }
     public BitmapImage imageHeader;
     public BitmapImage ImageHeader
     {
       get { return imageHeader; }
       set
       {
         imageHeader = value;
         OnPropertyChanged();
       }
     }
     public string myContents ;
     public string MyContents
     {
       get { return myContents; }
       set
       {
         myContents = value;
         OnPropertyChanged();
       }
     }
     protected void OnPropertyChanged([CallerMemberName] string name = null)
     {
       PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
     }
     public event PropertyChangedEventHandler PropertyChanged;
   }
 }

The result:
180540-8.gif

Update:
MainWindow.xaml:

 <Grid>
         <TabControl Height="300" ItemsSource="{Binding TabCollection}">
             <TabControl.ItemTemplate>
                 <DataTemplate>
                     <StackPanel>
                         <Label Content="{Binding DisplayIndex}" />
                         <Image Source="{Binding ContentObject.BackgroundImageSource}" Width="50"></Image>
                     </StackPanel>
                 </DataTemplate>
             </TabControl.ItemTemplate>
             <TabControl.ContentTemplate>
                 <DataTemplate>
                     <TextBlock Text="{Binding ContentObject.ShowContent}" />
                 </DataTemplate>
             </TabControl.ContentTemplate>
         </TabControl>
         <Button Content="Button" HorizontalAlignment="Left" Margin="273,391,0,0" VerticalAlignment="Top" Click="Button_Click"/>
     </Grid>

MainWindow.xaml.cs:

 using System;
 using System.Collections.Generic;
 using System.Collections.ObjectModel;
 using System.Windows;
 using System.Windows.Media.Imaging;
    
 namespace TabControlInerface
 {
     public partial class MainWindow : Window
     {
         public MainWindow()
         {
             vm = new WindowVM();
             this.DataContext = vm;
             InitializeComponent();
         }
         private WindowVM vm;
         private void Button_Click(object sender, RoutedEventArgs e)
         {
             vm.Init();
         }
     }
     public class WindowVM 
     {
         public ObservableCollection<Con> TabCollection { get; } = new ObservableCollection<Con>();
    
         public void Init()
         {
             List<Con> list = new List<Con>() { new Con()  };
             foreach (Con test in list)
             {
                 TabCollection.Add(test);
             }
         }
     }
     public interface ITestView
     {
         IContentTest ContentObject { get; set; }
         int DisplayIndex { get; set; }
     }
     public interface IContentTest
     {
         string ShowContent { get; set; }
         BitmapImage BackgroundImageSource { get; set; }
     }
     public class MyContent :IContentTest
     {
         public string ShowContent { get; set; }
         public BitmapImage BackgroundImageSource { get; set; }
         public MyContent()
         {
             ShowContent = "header1";
             BackgroundImageSource = new BitmapImage(new Uri("spring.jpg", UriKind.Relative));
         }
     }
     public class Con : ITestView
     {
         public IContentTest ContentObject { get; set; } = new MyContent();
         public int DisplayIndex { get; set; } = 1;
     }
 }

The result:
180993-image.png


If the response is helpful, please click "Accept Answer" and upvote it.
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.



8.gif (59.7 KiB)
image.png (11.9 KiB)
· 3
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Thanks for your reply!
But i want image data source from Interface, not direct in WindowVM. Are you having any ideas? :)

0 Votes 0 ·

Hi,@ SherryShi-6041 .You could refer to the update in my answer to bind the image from interface. I updated my answer, you can check it out.

0 Votes 0 ·

Thanks for your answer, it work !

0 Votes 0 ·