WPF ComboBox не обновляет источник - PullRequest
15 голосов
/ 27 февраля 2009

Я пытаюсь заставить работать комбинированный ящик WPF (внутри сетки данных WPFToolkit), и у меня возникают проблемы с выравниванием всех частей правильно. Я использую Linq для сущностей и задаю общий текстовый текст для результатов запроса 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 для выпадающего списка:


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

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

<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: Я все еще ломаю голову над этим. Я должен отметить, что в моей таблице данных любые простые столбцы данных (например, «DataGridTextColumn») обновляют базовый источник данных так, как вы ожидаете. Но любое обновление любого из моих шаблонных столбцов («DataGridTemplateColumn») или столбцов ComboBox («DataGridComboBoxColumn») не работает: базовый источник данных никогда не обновляется. Конечно, другие люди пытались использовать сетку данных WPF.Toolkit и заставили этот сценарий работать - но я рассмотрел весь пример кода, и я делаю в основном то, что он говорит (в рамках ограничений моего решение), поэтому я почесал голову, почему это не работает.

Есть мысли?

Ответы [ 3 ]

22 голосов
/ 18 февраля 2011

У меня была похожая проблема (на которую я потратил дни разочарования), и я обнаружил, что изменение 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" />
6 голосов
/ 20 марта 2009

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

  1. Я создал ViewModel в качестве контракта с View.
  2. Я привязался к свойству ComboBox.SelectedItem вместо свойства ComboBox.SelectedValue

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

Вот композиция из моего View Model:

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.

0 голосов
/ 12 июля 2011

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

IsSynchronizedWithCurrentItem = "True"

в вашем Xaml.

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

...