2 votes

WPF : Le changement de nom de l'en-tête basé sur le contexte ne fonctionne pas dans le Tabcontrol, il change pour tous les onglets lorsqu'il est utilisé avec des modèles.

J'ai un contrôle d'onglet avec un en-tête d'élément et des sélecteurs de modèle de contenu. L'en-tête de l'onglet a un en-tête à la fin comme "Ajouter un nouvel onglet". Le contenu de l'onglet est un contrôle d'utilisateur appelé Ladder avec un ensemble de contrôles. Les modèles sont liés à des modèles de vue et tout va bien.

    <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();
        }
    }
}

L'usercontrol a une combobox avec des entrées, si une entrée est sélectionnée, l'en-tête de l'onglet doit être changé avec cette entrée sélectionnée. J'utilise Gala Messenger pour transmettre le message entre les objets, donc lorsque la combobox est sélectionnée, le message est envoyé et l'en-tête est modifié en conséquence.

Le problème est que : il modifie l'en-tête de tous les onglets, je veux que l'en-tête de l'onglet ne soit modifié que si l'élément de la combobox est sélectionné dans cet onglet.

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");
        }
    }
}

Je veux savoir si c'est la bonne approche et si oui, quel est le problème et si non, quelle est la bonne approche.

Gracias

1voto

ASh Points 5948

MainWindowViewModel peut écouter le messager et modifier l'en-tête uniquement pour l'onglet sélectionné :

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 n'a pas d'abonnement :

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X