WPF ComboBox не обновляет источник
Я пытаюсь заставить работать поле со списком WPF (внутри WPFToolkit Datagrid), и у меня возникают проблемы с правильным выравниванием всех частей. Я использую Linq to Entities и устанавливаю общий текст данных на результаты запроса 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)3
У меня была аналогичная проблема (на которой я проводил дни разочарования), и я обнаружил , что изменение 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" />
Я смог заставить это работать. Но я устроил немного иначе.
- Я создал ViewModel, чтобы действовать как контракт с View.
- Я привязал к свойству ComboBox.SelectedItem вместо свойства ComboBox.SelectedValue
Поскольку я не знал, какой у вас источник данных, я создал свой собственный, чтобы смоделировать основную проблему: правильное связывание 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.