WPF combobox.SelectedItem не обновляется, если я использую DataTemplate для привязки виртуальной машины к представлению - PullRequest
0 голосов
/ 07 мая 2018

Я обнаружил, что WPF combobox.SelectedItem не обновляется, если я использую DataTemplate для привязки VM к View , но он будет обновляться, если я использую Просмотр напрямую. Вот мой код.

App.xaml

<Application.Resources>
    <DataTemplate DataType="{x:Type local:SalesPeriodVM}">
        <local:View />
    </DataTemplate>
</Application.Resources>

View.xaml

<Grid>
    <ComboBox ItemsSource="{Binding SalesPeriods}" SelectionChanged="ComboBox_SelectionChanged"
              SelectedItem="{Binding SelectedItem, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
              />
</Grid>

MainWindow.xaml.cs (код позади)

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

    }

    int currCount = 0;

    private void GotfocusClick(object sender, RoutedEventArgs e)
    {
        currCount = currCount+1;
        salesVM.SelectedItem = salesVM.SalesPeriods[currCount % salesVM.SalesPeriods.Count];
    }

}

MainWindow.xaml

<Window x:Class="SyncfusionWPF.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:syncfusion="http://schemas.syncfusion.com/wpf"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:SyncfusionWPF"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <local:SalesPeriodVM x:Name="salesVM"/>
    </Window.DataContext>

    <Grid>
        <TabControl x:Name="tabCOntrol1" Visibility="Visible">
            <TabItem Header="Item2" GotFocus="GotfocusClick">
            </TabItem>
            <TabItem Header="Item1">
                    <!--<local:View /> this works-->        
                <local:SalesPeriodVM /> <!--this doesn't work-->
            </TabItem>
        </TabControl>

    </Grid>
</Window>

Код моей модели просмотра:

public class SalesPeriodVM : INotifyPropertyChanged
{
    private ObservableCollection<SalesPeriodV> salesPeriods = new ObservableCollection<SalesPeriodV>();
    public ObservableCollection<SalesPeriodV> SalesPeriods
    {
        get { return salesPeriods; }
        set { salesPeriods = value; NotifyPropertyChanged("SalesPeriods"); }
    }
    private SalesPeriodV selectedItem = new SalesPeriodV();
    public SalesPeriodV SelectedItem
    {
        get { return selectedItem; }
        set { selectedItem = value; NotifyPropertyChanged("SelectedItem"); }


    }

    public SalesPeriodVM()
    {
        SalesPeriods.Add(new SalesPeriodV() { Month = 1, Year = 1 });
        SalesPeriods.Add(new SalesPeriodV() { Month = 2, Year = 1 });
        SalesPeriods.Add(new SalesPeriodV() { Month = 3, Year = 1 });
        SalesPeriods.Add(new SalesPeriodV() { Month = 4, Year = 1 });
        SalesPeriods.Add(new SalesPeriodV() { Month = 5, Year = 1 });
        SalesPeriods.Add(new SalesPeriodV() { Month = 6, Year = 1 });
        SalesPeriods.Add(new SalesPeriodV() { Month = 7, Year = 1 });
        SalesPeriods.Add(new SalesPeriodV() { Month = 8, Year = 1 });
        SalesPeriods.Add(new SalesPeriodV() { Month = 9, Year = 1 });
        SalesPeriods.Add(new SalesPeriodV() { Month = 10, Year = 1 });
        SalesPeriods.Add(new SalesPeriodV() { Month = 11, Year = 1 });
        SalesPeriods.Add(new SalesPeriodV() { Month = 12, Year = 1 });

        SelectedItem = SalesPeriods[1];
    }

    public virtual event PropertyChangedEventHandler PropertyChanged;
    protected virtual void NotifyPropertyChanged(params string[] propertyNames)
    {
        if (PropertyChanged != null)
        {
            foreach (string propertyName in propertyNames) PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            PropertyChanged(this, new PropertyChangedEventArgs("HasError"));
        }
    }
}

public class SalesPeriodV : INotifyPropertyChanged
{
    private int month, year;

    public int Year
    {
        get { return year; }
        set
        {
            if (year != value)
            {
                year = value;
                NotifyPropertyChanged("Year");
            }
        }
    }

    public int Month
    {
        get { return month; }
        set
        {
            if (month != value)
            {
                month = value;
                NotifyPropertyChanged("Month");
            }
        }
    }



    public override string ToString()
    {
        return String.Format("{0:D2}.{1}", Month, Year);
    }

    public virtual event PropertyChangedEventHandler PropertyChanged;
    protected virtual void NotifyPropertyChanged(params string[] propertyNames)
    {
        if (PropertyChanged != null)
        {
            foreach (string propertyName in propertyNames) PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            PropertyChanged(this, new PropertyChangedEventArgs("HasError"));
        }
    }
}

Итак, если я встраиваю <local:SalesPeriodVM /> в Item1, то когда Item2 получает фокус, combobox.SelectedItem в View не обновляется. Имейте в виду, что salesVM.SelectedItem действительно настроен. Просто пользовательский интерфейс не обновляется.

Что действительно интересно, так это то, что если я закомментирую <local:SalesPeriodVM /> и вместо этого вставлю <local:View /> в Item1, то когда я нажму на вкладку Item2, combobox.SelectedItem в представлении будет обновлено!

Я думал, что оба встраивания <local:SalesPeriodVM /> и <local:View /> должны быть эквивалентны, но почему это не так? Любая идея, как убедиться, что ComboBox.SelectedItem обновляется, если мне нужно используйте <local:SalesPeriodVM />?

1 Ответ

0 голосов
/ 15 мая 2018

Как указывает dymanoid , проблема в том, что существует два отдельных экземпляра local:SalesPeriodVM.

Первый экземпляр - это DataContext для окна. Второй - DataContext из View, расположенный во втором TabItem.

То, что отображается, это DataContext из View, расположенного во втором TabItem, но то, что изменяется, является первым, установленным как DataContext для Window.

Это объясняет, почему ComboBox.SelectedItem не обновляется.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...