繁体   English   中英

Silverlight 4:如何使组合框在打开时刷新其ItemsSource

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM