Вы можете узнать и узнать подробности из запроса ниже. Множественный столбец 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 Здесь
Ваш тип должен реализовать 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>
Правильное решение здесь состоит в том, чтобы использовать ObservableCollection <> для Вашего свойства ListBox IetmsSource. WPF автоматически обнаружит любые изменения в содержании этого набора и вынудит соответствующий ListBox обновить для отражения изменений.
Можно хотеть прочитать эту статью MSDN для получения дополнительной информации. Это было записано, чтобы конкретно объяснить, как обработать этот сценарий
http://msdn.microsoft.com/en-us/magazine/dd252944.aspx?pr=blog
Попытайтесь реализовать интерфейс INotifyPropertyChanged на своих объектах FooBar. Когда они изменяют, генерируют события PropertyChanged, передавая строку. Пустой как имя свойства. Это должно добиться цели.
Вот код 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.
Если объект коллекции, который Вы используете для хранения объектов, является observablecollection <> затем, это обрабатывается для Вас.
т.е. если набор будет изменен, то любые средства управления, связанные с данными к нему, будут обновлены и наоборот.