[英]How to refresh ListBox.ItemsSource in a SilverLight 3 project?
[英]Silverlight 4: How to make a combobox refresh its ItemsSource on open
我想在打开时刷新Silverlight 4组合框的内容。
这似乎是一件愚蠢而简单的事情,但我终生无法找到一个直接的答案。
我在Silverlight 4应用程序中有一个带有组合框的表格,其中列出了销售订单号。 许多人会同时打开此表单,所以我希望它可以回叫“打开”的Web服务并刷新其内容。
我发现的最接近的东西是:
http://blogs.msdn.com/b/kylemc/archive/2010/06/18/combobox-sample-for-ria-services.aspx
..我无法工作,也无济于事。 该示例中没有什么可以让我在下拉列表打开时重新填充它。
我正在使用MVVM,并且已使用Interactivity类将组合框的Open事件泵入到ViewModel中。 在那里,我调用了Web服务,并重置了组合框的ItemsSource绑定到的基础属性。 不起作用-下拉菜单闪烁一秒钟,然后打开,为空。
更新:
XAML:
<ComboBox x:Name="cmbOrderNumber" Width="125"
ItemsSource="{Binding ActiveSalesOrderNumbers, Mode=TwoWay}"
IsEnabled="{Binding OrderSelectorEnabled}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<inf:InvokeDelegateCommandAction Command="{Binding SalesOrderSelectedCommand}" CommandParameter="{Binding ElementName=cmbOrderNumber, Path=SelectedValue}"></inf:InvokeDelegateCommandAction>
</i:EventTrigger>
<i:EventTrigger EventName="DropDownOpened">
<inf:InvokeDelegateCommandAction Command="{Binding SalesOrderOpenedCommand}"></inf:InvokeDelegateCommandAction>
</i:EventTrigger>
</i:Interaction.Triggers>
</ComboBox>
C#:
public void OnSalesOrderOpenedCommand(object o)
{
_companyContext.Load(_companyContext.GetSales_Order_Numbers_FromDateQuery(_lastSalesOrderRequest), q =>
{
if (!q.HasError)
{
q.Entities.ToList().ForEach(e =>
{
ActiveSalesOrderNumbers.Add(e.Sales_Order_Number);
});
_lastSalesOrderRequest = DateTime.Now;
}
else
{
throw new Exception("Error updating sales order number list.");
}
}, null);
}
事件被触发,我已经看到数据从服务中按预期返回,并将新项目添加到ActiveSalesOrderNumbers
,这是一个ObservableCollection。 下拉列表不更新,没有新记录。
您的项目清单是什么样的? 如果将ItemsSource
绑定到ViewModel上的ObservableCollection<T>
上,则您应该能够从该集合中添加/删除项目,并且ComboBox
项将正确更新。 一旦将ComboBox设置一次,它就会真正破坏绑定。 我建议不要尝试替换整个ItemsSource,而要使用ObservableCollection<T>
, Clear()
然后Add(...)
。
我正在做一个项目,所以我现在正在做一个项目,因此我可以验证它是否有效。
编辑:
MainPage.xaml中
<ComboBox
x:Name="comboBox"
ItemsSource="{Binding ActiveSalesOrderNumbers}"
HorizontalAlignment="Center"
Width="200"
Height="27"
Margin="30">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel
Orientation="Horizontal">
<TextBlock>
<Run Text="{Binding SalesOrderNumber}"/>
<Run Text="{Binding LastModified}"/>
</TextBlock>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
<i:Interaction.Triggers>
<i:EventTrigger EventName="DropDownOpened">
<ei:CallMethodAction MethodName="OnSalesOrderOpenedCommand" TargetObject="{Binding DataContext, ElementName=comboBox}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ComboBox>
MainPage.xaml.cs中
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
this.DataContext = new MainPageViewModel();
}
}
MainPageViewModel.cs
public class MainPageViewModel : NotifyObject
{
private readonly SalesOrderRepository _repository;
public MainPageViewModel()
: this(new SalesOrderRepository())
{
}
public MainPageViewModel(SalesOrderRepository repository)
{
_repository = repository;
this.ActiveSalesOrderNumbers = new ObservableCollection<SalesOrder>();
}
private ObservableCollection<SalesOrder> _activeSalesOrderNumbers;
public ObservableCollection<SalesOrder> ActiveSalesOrderNumbers
{
get { return _activeSalesOrderNumbers; }
set
{
_activeSalesOrderNumbers = value;
NotifyPropertyChanged(() => ActiveSalesOrderNumbers);
}
}
public void OnSalesOrderOpenedCommand()
{
_repository.GetSalesOrderNumbers(result =>
{
this.ActiveSalesOrderNumbers.Clear();
result.ToList().ForEach(e => { this.ActiveSalesOrderNumbers.Add(e); });
});
}
}
public class SalesOrder : NotifyObject
{
private string _salesOrderNumber;
public string SalesOrderNumber
{
get { return _salesOrderNumber; }
set
{
_salesOrderNumber = value;
NotifyPropertyChanged(() => SalesOrderNumber);
}
}
private DateTime _lastModified;
public DateTime LastModified
{
get { return _lastModified; }
set
{
_lastModified = value;
NotifyPropertyChanged(() => LastModified);
}
}
}
public class SalesOrderRepository
{
public void GetSalesOrderNumbers(Action<IEnumerable<SalesOrder>> reply)
{
List<SalesOrder> orders = new List<SalesOrder>();
for (int i = 0; i < 10; i++)
{
orders.Add(new SalesOrder { SalesOrderNumber = i.ToString(), LastModified = DateTime.Now });
}
reply(orders);
}
}
NotifyObject.cs
public abstract class NotifyObject : INotifyPropertyChanged
{
/// <summary>
/// Occurs when a property value changes.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged = delegate { };
/// <summary>
/// Raises this object's PropertyChanged event.
/// </summary>
/// <param name="propertyName">The property that has a new value.</param>
protected void NotifyPropertyChanged(string propertyName)
{
this.VerifyPropertyName(propertyName);
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
{
var e = new PropertyChangedEventArgs(propertyName);
handler(this, e);
}
}
/// <summary>
/// Raises this object's PropertyChanged event.
/// </summary>
/// <typeparam name="TProperty">The type of the property.</typeparam>
/// <param name="property">The property.</param>
protected void NotifyPropertyChanged<TProperty>(Expression<Func<TProperty>> property)
{
var lambda = (LambdaExpression)property;
MemberExpression memberExpression;
if (lambda.Body is UnaryExpression)
{
var unaryExpression = (UnaryExpression)lambda.Body;
memberExpression = (MemberExpression)unaryExpression.Operand;
}
else memberExpression = (MemberExpression)lambda.Body;
NotifyPropertyChanged(memberExpression.Member.Name);
}
/// <summary>
/// Warns the developer if this object does not have
/// a public property with the specified name. This
/// method does not exist in a Release build.
/// </summary>
[Conditional("DEBUG")]
public void VerifyPropertyName(string propertyName)
{
// If you raise PropertyChanged and do not specify a property name,
// all properties on the object are considered to be changed by the binding system.
if (String.IsNullOrEmpty(propertyName))
return;
// Verify that the property name matches a real,
// public, instance property on this object.
if (this.GetType().GetProperties().Where(p => p.Name == propertyName).FirstOrDefault() == null)
{
throw new ArgumentException(String.Format("Invalid property name: {0}", propertyName));
}
}
}
为了能够在代码隐藏文件中绑定源,您需要使该文件具有DepencyProperty才能正常工作,例如:
#region Title (DependenyProperty)
public String Title
{
get { return (String)GetValue(TitleProperty); }
set { SetValue(TitleProperty, value); }
}
public static readonly DependencyProperty TitleProperty =
DependencyProperty.Register("Title", typeof(String), typeof(TopicListItem), new PropertyMetadata(null));
#endregion String (DependenyProperty)
我了解的是它的运作方式。 您无需创建string
即可创建需要创建的集合对象。 告诉我们情况如何。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.