Обновление WPF перечисляет, когда объект изменяется

Вы можете узнать и узнать подробности из запроса ниже. Множественный столбец OrderBy полезен, когда аналогичные значения присутствуют в таблице.

Create Table Orders (Id int, ProdName Varchar(20))
insert into Orders Values (1, 'A'), (4, 'C'), (2, 'B'), (3, 'E'), (4, 'G'), (5, 'D'), (6, 'F'), (7, 'G')

Select * from Orders
order by 1 -- Order By Id Ascending

Select * from Orders
order by 1 desc -- Order By Id Descending

Select * from Orders
order by 2 -- Order By Name Ascending

Select * from Orders
order by 2 desc -- Order By Name Descending

Select * from Orders
order by 1, 2 -- Order By Id first and then Name Ascending. 
-- It will come same Id first and same name later

Select * from Orders
order by 1 asc, 2 desc --First priority of Id ascending then Name in descending order

Select * from Orders
order by 1, 2 desc

Вы можете найти живое демо Live Demo Здесь

12
задан Dave Clemmer 25 August 2011 в 15:16
поделиться

5 ответов

Ваш тип должен реализовать INotifyPropertyChanged так, чтобы набор мог обнаружить изменения. Поскольку Sam говорит, передача string.Empty как аргумент.

Вы также должны иметь ListBoxисточник данных быть набором, который предоставляет уведомление об изменении. Это сделано через INotifyCollectionChanged интерфейс (или not-so-WPF IBindingList интерфейс).

Конечно, Вам нужно INotifyCollectionChanged взаимодействуйте через интерфейс для увольнения каждый раз, когда один из участника INotifyPropertyChanged объекты запускают его событие. К счастью существует несколько типов в платформе, которые предоставляют эту логику Вам. Вероятно, самый подходящий ObservableCollection<T>. Если Вы связываете Ваш ListBox к ObservableCollection<FooBar> затем объединение в цепочку события произойдет автоматически.

На связанной ноте Вы не должны использовать a ToString метод только, чтобы заставить WPF представлять объект в способе, которым Вы хотите. Можно использовать a DataTemplate как это:

<ListBox x:Name="listBox1">
    <ListBox.Resources>
        <DataTemplate DataType="{x:Type local:FooBar}">
            <TextBlock Text="{Binding Path=Property}"/>
        </DataTemplate>
    </ListBox.Resources>
</ListBox>

Таким образом можно управлять презентацией объекта, где это принадлежит - XAML.

ОТРЕДАКТИРУЙТЕ 1, я заметил Ваш комментарий, что Вы используете ListBox.Items набор как Ваш набор. Это не сделает требуемой привязки. Вы - более обеспеченное выполнение чего-то как:

var collection = new ObservableCollection<FooBar>();
collection.Add(fooBar1);

_listBox.ItemsSource = collection;

Я не проверил, что код для точности компиляции, но Вы получаете суть.

ОТРЕДАКТИРУЙТЕ 2 Используя DataTemplate Я дал выше (я отредактировал его для установки код) решает проблему.

Это кажется странным то увольнение PropertyChanged не заставляет элемент списка обновлять, но затем использование ToString метод не является способом, которым WPF был предназначен для работы.

Используя этот DataTemplate, UI связывает правильно с точным свойством.

Я задал вопрос на здесь некоторое время назад о выполнении строкового форматирования в привязке WPF. Вы могли бы найти это полезным.

ОТРЕДАКТИРУЙТЕ 3, я экранирован относительно того, почему это все еще не работает на Вас. Вот полный исходный код для окна, которое я использую.

Код позади:

using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;

namespace StackOverflow.ListBoxBindingExample
{
    public partial class Window1
    {
        private readonly FooBar _fooBar;

        public Window1()
        {
            InitializeComponent();

            _fooBar = new FooBar("Original value");

            listBox1.ItemsSource = new ObservableCollection<FooBar> { _fooBar };
        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            _fooBar.Property = "Changed value";
        }
    }

    public sealed class FooBar : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private string m_Property;

        public FooBar(string initval)
        {
            m_Property = initval;
        }

        public string Property
        {
            get { return m_Property; }
            set
            {
                m_Property = value;
                OnPropertyChanged("Property");
            }
        }

        private void OnPropertyChanged(string propertyName)
        {
            var handler = PropertyChanged;
            if (handler != null)
                handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

XAML:

<Window x:Class="StackOverflow.ListBoxBindingExample.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:StackOverflow.ListBoxBindingExample"
    Title="Window1" Height="300" Width="300">
    <DockPanel LastChildFill="True">
        <Button Click="button1_Click" DockPanel.Dock="Top">Click Me!</Button>
        <ListBox x:Name="listBox1">
            <ListBox.Resources>
                <DataTemplate DataType="{x:Type local:FooBar}">
                    <TextBlock Text="{Binding Path=Property}"/>
                </DataTemplate>
            </ListBox.Resources>
        </ListBox>
    </DockPanel>
</Window>
13
ответ дан 2 December 2019 в 19:33
поделиться

Правильное решение здесь состоит в том, чтобы использовать ObservableCollection <> для Вашего свойства ListBox IetmsSource. WPF автоматически обнаружит любые изменения в содержании этого набора и вынудит соответствующий ListBox обновить для отражения изменений.

Можно хотеть прочитать эту статью MSDN для получения дополнительной информации. Это было записано, чтобы конкретно объяснить, как обработать этот сценарий

http://msdn.microsoft.com/en-us/magazine/dd252944.aspx?pr=blog

3
ответ дан 2 December 2019 в 19:33
поделиться

Попытайтесь реализовать интерфейс INotifyPropertyChanged на своих объектах FooBar. Когда они изменяют, генерируют события PropertyChanged, передавая строку. Пустой как имя свойства. Это должно добиться цели.

1
ответ дан 2 December 2019 в 19:33
поделиться

Вот код C#, у меня есть работа для этого:

using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.ComponentModel;
using System.Collections.ObjectModel;
namespace ListboxOfFoobar
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            ObservableCollection<FooBar> all = (ObservableCollection<FooBar>)FindResource("foobars");
            all[0].P1 = all[0].P1 + "1";
        }
    }
    public class FooBar : INotifyPropertyChanged
    {
        public FooBar(string a1, string a2, string a3, string a4)
        {
            P1 = a1;
            P2 = a2;
            P3 = a3;
            P4 = a4;
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged(String info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }

        private String p1;
        public string P1
        {
            get { return p1; }
            set
            {
                if (value != this.p1)
                {
                    this.p1 = value;
                    NotifyPropertyChanged("P1");
                }
            }
        }
        private String p2;
        public string P2
        {
            get { return p2; }
            set
            {
                if (value != this.p2)
                {
                    this.p2 = value;
                    NotifyPropertyChanged("P2");
                }
            }
        }
        private String p3;
        public string P3
        {
            get { return p3; }
            set
            {
                if (value != this.p3)
                {
                    this.p3 = value;
                    NotifyPropertyChanged("P3");
                }
            }
        }
        private String p4;
        public string P4
        {
            get { return p4; }
            set
            {
                if (value != this.p4)
                {
                    this.p4 = value;
                    NotifyPropertyChanged("P4");
                }
            }
        }
        public string X
        {
            get { return "Foooooo"; }
        }
    }
    public class Foos : ObservableCollection<FooBar>
    {
        public Foos()
        {
            this.Add(new FooBar("a", "b", "c", "d"));
            this.Add(new FooBar("e", "f", "g", "h"));
            this.Add(new FooBar("i", "j", "k", "l"));
            this.Add(new FooBar("m", "n", "o", "p"));
        }
    }
}

Вот XAML:

<Window x:Class="ListboxOfFoobar.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:ListboxOfFoobar"
    xmlns:debug="clr-namespace:System.Diagnostics;assembly=System"

    Title="Window1" Height="300" Width="300"        
        >
    <Window.Resources>
        <local:Foos x:Key="foobars" />
        <DataTemplate x:Key="itemTemplate">
            <StackPanel Orientation="Horizontal">
                <TextBlock MinWidth="80" Text="{Binding Path=P1}"/>
                <TextBlock MinWidth="80" Text="{Binding Path=P2}"/>
                <TextBlock MinWidth="80" Text="{Binding Path=P3}"/>
                <TextBlock MinWidth="80" Text="{Binding Path=P4}"/>
            </StackPanel>
        </DataTemplate>

    </Window.Resources>

    <DockPanel>
        <ListBox DockPanel.Dock="Top"
         ItemsSource="{StaticResource foobars}"
         ItemTemplate="{StaticResource itemTemplate}" Height="229" />
        <Button  Content="Modify FooBar" Click="Button_Click" DockPanel.Dock="Bottom" />
    </DockPanel>
</Window>

Нажатие Кнопки заставляет первое свойство первого FooBar быть обновленным и чтобы это показало в ListBox.

1
ответ дан 2 December 2019 в 19:33
поделиться

Если объект коллекции, который Вы используете для хранения объектов, является observablecollection <> затем, это обрабатывается для Вас.

т.е. если набор будет изменен, то любые средства управления, связанные с данными к нему, будут обновлены и наоборот.

0
ответ дан 2 December 2019 в 19:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: