【问题标题】:How to bind and auto update listbox wpf如何绑定和自动更新列表框 wpf
【发布时间】:2014-08-11 22:31:14
【问题描述】:

好的,这里有几个问题

第一

这是我的实现,但在 atm 不工作我怎样才能让它工作?

    <Grid> // xaml part
    <Button Content="Start Crawling Root Sites - This Deletes All Data" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="279" Command="{Binding StartCrawling}" Click="click_start_Crawling"  />
    <ListBox Name="lstBoxEvents" HorizontalAlignment="Left"  Height="138" Margin="294,10,0,0" VerticalAlignment="Top" Width="312">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <Grid Margin="1">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto" />
                    </Grid.ColumnDefinitions>
                    <TextBlock Grid.Column="1" Text="{Binding ocEvents}"  />
                </Grid>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</Grid>


        private void click_start_Crawling(object sender, RoutedEventArgs e) // inside mainwindow
    {
        PublicStaticFunctions.AddMsgToEvents("trial");
    }

    public static class PublicStaticFunctions // seperate class
{
    public static ObservableCollection<string> ocEvents = new ObservableCollection<string>();

    public static void AddMsgToEvents(string srMessage)
    {
        ocEvents.Insert(0, srMessage);
    }
}

我在运行多线程时的第二个问题,如果多个线程访问 AddMsgToEvents 函数并添加变量,列表框是否仍会自动刷新而没有任何问题?

非常感谢

【问题讨论】:

  • 到底是什么问题? ListBox 需要有一个ItemsSource。只要源是ObservableCollection,它就应该在添加/删除时将更改传播到 UI。
  • @PoweredByOrange 仍然无法正常工作 fc03.deviantart.net/fs71/f/2014/223/5/5/… 未更新
  • ItemSource={binding ocEvents}
  • @PoweredByOrange 也不起作用

标签: c# wpf multithreading binding listbox


【解决方案1】:

这一行:

public static ObservableCollection<string> ocEvents = new ObservableCollection<string>();

这既不是依赖属性也不是实现 INotifyPropertyChanged 的​​属性,它也是静态的,如果您使用视图模型,您可以按照下面描述的方式进行操作,您可以在代码隐藏中进行操作,但它会调用双重重绘。无论如何,您需要将其更改为如下所示的 DP 或道具:

private ObservableCollection<string> ocEvents = new ObservableCollection<string>();
public ObservableCollection<string> OcEvents
{
    get { return ocEvents; }
    set
    {
        if (Equals(value, ocEvents)) return;
        ocEvents = value;
        OnPropertyChanged();
    }
}
public event PropertyChangedEventHandler PropertyChanged;

[NotifyPropertyChangedInvocator] // Comment out if you don't have R#
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
    PropertyChangedEventHandler handler = PropertyChanged;
    if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}

绑定到静态类/属性有一些奇怪之处,你必须以不同的方式绑定。我现在要睡觉了,所以我无法提供示例。在上述情况下,我将创建一个 vm,以及一个用于获取我的事件的服务,而不是使我的 vm 可单元测试(创建提供事件的服务的接口,并在 vm 上具有 event 属性)。

AddMsgToEvents() 必须在调度程序线程上调用。一个不好的技巧是添加以下代码。调用它

    BeginInvoke(YourMethod);

将代码添加到虚拟机的基类中,我知道调度程序应该以这种方式“使用”,但只是为了简单。

    public void BeginInvoke(Action action)
    {
        if( Application.Current.Dispatcher.CheckAccess())                
            Application.Current.Dispatcher.BeginInvoke(action);
        else
        {
            action();
        }
    }

    public void Invoke(Action action)
    {
        if (Application.Current.Dispatcher.CheckAccess())
            Application.Current.Dispatcher.BeginInvoke(action);
        else
        {
            action();
        }
    }


public static class PublicStaticFunctions

你的服务就在那里,只是取消静态并创建它的接口:D 将你的道具移动到 vm/codebehind,或者你需要对那里的绑定进行一些更改,再加上一个道具或 DP。简短的回答。

编辑:服务示例

public interface IEventService
{
    ObservableCollection<String> GetEvents();
    void AddEvent(String eventToAdd);
}

public  class EventService : IEventService
{
    private readonly ObservableCollection<string> events;

    public EventService(ObservableCollection<string> events)
    {
        this.events = events;
    }

    public EventService()
    {
        events = new ObservableCollection<string>();
    }

    public ObservableCollection<string> Events
    {
        get { return events; }
        //set { events = value; }
    }

    public ObservableCollection<String> GetEvents()
    {
        return events;
    }

    public void AddEvent(String eventToAdd)
    {
        events.Add(eventToAdd);
    }
}

将此接口提供给 vm 的 ctor(TDD :) ) 或代码隐藏 ctor。将其分配并存储在 IOC 容器、服务定位器或其他任何东西中。

希望对你有帮助,

干杯,

斯蒂安

【讨论】:

  • 回答,但我真的需要绑定到静态对象:/
  • @MonsterMMORPG 我尽可能避免使用静态,不,您不需要静态绑定。使您的事物(数据提供者类)成为非静态服务(带有接口),然后制作视图模型并将其用作数据上下文或使用代码隐藏。使您的 ocEvents(应该是 OcEvents 或只是事件;))与 inot 正确。或代码隐藏中的 vm 或 dp。 R# = 锐化器
  • 如果我是非静态的,我将如何从不同的类访问它?
  • 如果您查看诸如 galasoft mvvm light 和 DI 或 ServiceLocator 模式之类的框架(我个人认为这是一种反模式)。您会看到一个像您几乎在那里所做的那样创建服务,并创建一个界面。接口被传递给 viewmodels 构造函数。这样您就可以找到您的数据。但是静态绑定是可能的,例如使用实例或直接绑定。但我现在得去睡觉了。希望我对你有所帮助。
  • 好吧,我使它与删除 并以这种方式绑定 ItemsSource="{x:Static local:PublicStaticFunctions.ocEventsCollection }" 但我如何保留 ItemTemplate :D
猜你喜欢
  • 2014-08-06
  • 1970-01-01
  • 2011-02-28
  • 2014-02-22
  • 2021-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多