WPF ComboBox не обновляет источник

Я пытаюсь получить комбобокс WPF (внутри WPFToolkit Datagrid), и у меня возникают проблемы с правильной настройкой всех частей. Я использую Linq для Entities, и я устанавливаю общий datacontext для результатов запроса Linq:


private void LoadDonationGrid()
{
    donationGrid.ItemsSource = from donations in entities.Donation
                   .Include("Family")
                   .Include("PledgeYear")
                   .Include("DonationPurpose")
               from donationPurposes in entities.DonationPurpose
               select new { donations, donationPurposes };
}

У меня также есть свойство страницы в моем коде, которое предоставляет ItemsSource для combobox:


private IEnumerable donationPurposeList;
public IEnumerable DonationPurposeList
{
    get
    {
        if (donationPurposeList == null)
        {
            donationPurposeList = from dp in entities.DonationPurpose
                                  select dp;
        }
        return donationPurposeList.ToList();
    }
}

XAML для combobox выглядит следующим образом:

<tk:DataGridTemplateColumn Header="Purpose">
    <tk:DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Path=donations.DonationPurpose.Description, Mode=TwoWay}" />
        </DataTemplate>
    </tk:DataGridTemplateColumn.CellTemplate>
    <tk:DataGridTemplateColumn.CellEditingTemplate>
        <DataTemplate>
            <ComboBox Name="cboDonationPurpose"
                SelectedValue="{Binding Path=donations.DonationPurposeID, Mode=TwoWay}"
                ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type Page},Mode=FindAncestor},Path=DonationPurposeList}"                                 
                DisplayMemberPath="Description"
                SelectedValuePath="DonationPurposeID"
                      />
        </DataTemplate>
    </tk:DataGridTemplateColumn.CellEditingTemplate>
</tk:DataGridTemplateColumn>

И все, кажется, работает правильно, то есть соответствующие значения отображаются в ComboBox, вплоть до того момента, когда фокус покидает ComboBox. В этот момент отображаемое значение возвращается к исходному значению, а не к вновь выбранному значению. Я пробовал использовать SelectedItem вместо SelectedValue, но это заканчивается выбранным значением, которое не отображается в ComboBox. Я немного озадачен: похоже, этот бит должен работать.

Отредактировано 3/2/09: Я все еще озадачиваюсь этим. Следует отметить, что в моем datagrid любые простые столбцы данных (например, "DataGridTextColumn" ) обновляют базовый источник данных так же, как вы ожидали. Но любое обновление для любого из моих шаблонных столбцов ( "DataGridTemplateColumn" ) или столбцов ComboBox ( "DataGridComboBoxColumn" ) не работает: базовый источник данных никогда не обновляется. Конечно, другие люди пытались использовать WPF.Toolkit datagrid и получили этот сценарий для работы, но я посмотрел на весь образец кода там, и я делаю в основном то, что он говорит (в рамках ограничений моего решение), поэтому я почесываю голову, почему это не работает.

Любые мысли?

Ответы

Ответ 1

У меня была аналогичная проблема (на которой я провел дни разочарования), и я обнаружил, что изменение UpdateSourceTrigger в привязке SelectedValue к PropertyChanged исправило ее. Я не знаю, почему, но для меня источник данных не обновлялся, пока я не сделал это изменение.

<ComboBox 
    ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UpdateTypesManager:MainWindow}}, Path=CardinalityTypes}" 
    DisplayMemberPath="CardinalityType"
    SelectedValue="{Binding CardinalityTypeId, UpdateSourceTrigger=PropertyChanged}"
    SelectedValuePath="Id" />

Ответ 2

Я смог получить эту работу. Но я поставил вещи немного по-другому.

  • Я создал ViewModel для работы в качестве контракта с представлением.
  • Я привязался к свойству ComboBox.SelectedItem вместо ComboBox.SelectedValue Property

Так как я не знал, каким был ваш источник данных, я составил свой собственный, чтобы имитировать основную проблему: правильная привязка comboBox в WPF DataGrid.

Вот композиция моей модели просмотра:

public class RootViewModel
{
    public List<State> USStates { get; set; }
    public List<Customer> Customers { get; set; }

    public ViewModel()
    {
        Customers = new List<Customer>();
        Customers.Add(new Customer() { FirstName = "John", LastName = "Smith", State = new State() { ShortName = "IL" } });
        Customers.Add(new Customer() { FirstName = "John", LastName = "Doe", State = new State() { ShortName = "OH" } });
        Customers.Add(new Customer() { FirstName = "Sally", LastName = "Smith", State = new State() { ShortName = "IN" } });

        USStates = new List<State>();
        USStates.Add(new State() { ShortName = "OH" });
        USStates.Add(new State() { ShortName = "IL" });
        USStates.Add(new State() { ShortName = "IN" });
    }
}

public class Customer
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public State State { get; set; }
}

public class State
{
    public string ShortName { get; set; }

    public State() 
    {
        ShortName = string.Empty;
    }

    public override bool Equals(object obj)
    {
        if (obj is State)
        {
            State otherState = obj as State;
            return ShortName.Equals(otherState.ShortName);
        }
        else
        {
            return false;
        }
    }
}

Прежде чем начать, я установил DataContext моего окна как экземпляр моего правильно построенного RootViewModel.

<tk:DataGrid ItemsSource="{Binding Customers}" AutoGenerateColumns="False">
            <tk:DataGrid.Columns>
                <tk:DataGridTemplateColumn Header="State">
                    <tk:DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding Path=State.ShortName, Mode=TwoWay}" />
                        </DataTemplate>
                    </tk:DataGridTemplateColumn.CellTemplate>
                    <tk:DataGridTemplateColumn.CellEditingTemplate>
                        <DataTemplate>
                            <ComboBox 
                                x:Name="cboDonationPurpose" 
                                SelectedItem="{Binding Path=State, Mode=TwoWay}" 
                                ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window},Mode=FindAncestor}, Path=DataContext.USStates}" 
                                DisplayMemberPath="ShortName" 
                                SelectedValuePath="ShortName" />
                        </DataTemplate>
                    </tk:DataGridTemplateColumn.CellEditingTemplate>
                </tk:DataGridTemplateColumn>
            </tk:DataGrid.Columns>
        </tk:DataGrid>

Для правильной привязки SelectedItem мне нужно убедиться, что я переопределил метод Equals на моем объекте, так как под капотом WPF использует этот метод для определения того, кто является SelectedItem или нет. Я думаю, что это была принципиально ваша проблема с самого начала, которая заставила вас попытаться привязать к SelectedValue вместо SelectedItem.

Ответ 3

Вам нужно добавить

IsSynchronizedWithCurrentItem = "True"

в вашем Xaml.

Это так просто...