Home > other >  WPF: Context based header name change does not work in Tabcontrol, instead it changes for all tabs w
WPF: Context based header name change does not work in Tabcontrol, instead it changes for all tabs w

Time:07-12

I have a tab control with Item header and Content template selectors The tab header has a header at the end as "Add new tab". The content of the tab is a usercontrol called Ladder with a set of controls. templates are binded with viewmodels and all is fine.

    <Grid.Resources>
        <DataTemplate x:Key="newTabButtonContentTemplate"/>

        <DataTemplate x:Key="newTabButtonHeaderTemplate">
            <Button Content="Add New Tab" Command="{Binding ElementName=parentUserControl, Path=DataContext.NewCommand}" 
                     HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch">
            </Button>
        </DataTemplate>

        <DataTemplate x:Key="itemContentTemplate" DataType="{x:Type localNS:ItemViewModel}">
            <views:Ladder DataContext="{Binding ItemLadderViewModel}"/>
        </DataTemplate>

        <DataTemplate x:Key="itemHeaderTemplate" DataType="{x:Type localNS:ItemViewModel}">
            <TextBlock Text="{Binding Header}"/>
        </DataTemplate>

        <templates:TemplateSelector x:Key="headerTemplateSelector"
                       NewButtonTemplate="{StaticResource newTabButtonHeaderTemplate}"
                       ItemTemplate="{StaticResource itemHeaderTemplate}"/>

        <templates:TemplateSelector x:Key="contentTemplateSelector"
                        NewButtonTemplate="{StaticResource newTabButtonContentTemplate}"
                        ItemTemplate="{StaticResource itemContentTemplate}"/>
    </Grid.Resources>
    

ViewModels

MainWindowViewModel

    public MainWindowViewModel()
    {
        this.newCommand = new CustomDelegateCommand(
                () =>
                {
                    var itemViewModel = new ItemViewModel(); 
                    Items.Add(itemViewModel);
                    this.CurrentSelectedItem = itemViewModel;
                }
            );
    }

    private ObservableCollection<ItemViewModel> items;
    public ObservableCollection<ItemViewModel> Items
    {
        get
        {
            if (items == null)
            {
                items = new ObservableCollection<ItemViewModel>();
                var itemViewModel = new ItemViewModel();
                Items.Add(itemViewModel);
                this.CurrentSelectedItem = itemViewModel;
                var itemsView = (IEditableCollectionView)CollectionViewSource.GetDefaultView(items);
                itemsView.NewItemPlaceholderPosition = NewItemPlaceholderPosition.AtEnd;
            }

            return items;
        }
    }

    public ItemViewModel CurrentSelectedItem
    {
        get { return this.currentSelectedItem; }
        set
        {
            this.currentSelectedItem = value;
            this.OnPropertyChanged();
        }
    }

ItemViewModel

public class ItemViewModel : BindableBase
{
    private string header = "New Tab";
    private LadderViewModel itemLadderViewModel;

    public ItemViewModel()
    {
        itemLadderViewModel = new LadderViewModel();
        Messenger.Default.Register<Instrument>(this, "InstrumentChanged", instrument =>
        {
            this.Header = instrument.FullName;
        });
    }

    public LadderViewModel ItemLadderViewModel
    {
        get { return itemLadderViewModel; }
    }

    public string Header
    {
        get { return header; }
        set
        {
            header = value;
            OnPropertyChanged();
        }
    }
}

the usercontrol has a combobox with entries in that, if any entry is selected the tab header should be changed with that selected entry. I am using gala messenger to pass the message between objects, so when combobox is selected message is sent and the header is changed accordingly, this is also working but

The problem is: it changes the header of all tabs, I want the header of the tab to be changed only with the combobox item selected in that tab.

public class LadderViewModel : BindableBase
{
    private Instrument ladderInstrumentName = null;

    public Instrument LadderInstrumentName
    {
        get
        {
            return this.ladderInstrumentName;
        }
        set
        {
            this.ladderInstrumentName = value;
            Messenger.Default.Send<Instrument>(value, "InstrumentChanged");
        }
    }
}

I want to know if this is the right approach of doing it and if yes what is the issue and if not then what is the right approach.

Thanks

CodePudding user response:

MainWindowViewModel can listen messenger and change header only for selected tab:

public MainWindowViewModel()
{
    this.newCommand = new CustomDelegateCommand(
            () =>
            {
                var itemViewModel = new ItemViewModel(); 
                Items.Add(itemViewModel);
                this.CurrentSelectedItem = itemViewModel;
            }
        );

    Messenger.Default.Register<Instrument>(this, "InstrumentChanged", instrument =>
    {
        if (CurrentSelectedItem != null) CurrentSelectedItem.Header = instrument.FullName;
    });
}

ItemViewModel doesn't have subscription:

public ItemViewModel()
{
    itemLadderViewModel = new LadderViewModel();
    /*Messenger.Default.Register<Instrument>(this, "InstrumentChanged", instrument =>
    {
        this.Header = instrument.FullName;
    });*/
}
  • Related