使用例如ObservableCollection(OC)司機是正確的做法。此外使用CollectionViewSource(CVS)也是一個好方法。在你的情況下產生的問題是,當源(OC)發生變化時,你的CVS纔會被實現。這意味着如果驅動程序被添加或刪除。
當您的源對象的屬性(如「BestLap」)更改時,您需要通知您。
在stackoverflow和其他網站處理這個問題有幾個問題/答案。
我們可能的解決方案(從第二鏈路中提取):啓用 「IsLiveSortingRequested」 並添加一個 「SortDescription」 含有被用於排序的特性。
<Window.Resources>
<CollectionViewSource x:Key="cvsDrivers" Source="{Binding DriversList}" IsLiveSortingRequested="True">
<CollectionViewSource.LiveSortingProperties>
<clr:String>BestLap</clr:String>
</CollectionViewSource.LiveSortingProperties>
<CollectionViewSource.SortDescriptions>
<scm:SortDescription PropertyName="BestLap" />
</CollectionViewSource.SortDescriptions>
</CollectionViewSource>
</Window.Resources>
編輯:
這裏是使用適當的方法MVVM一個(非常簡單和基本的)工作實施例:
模型(driver.cs):
public class Driver : INotifyPropertyChanged
{
private string name;
public string Name
{
get { return name; }
set
{
name = value;
OnPropertyChanged("Name");
}
}
private double bestLap;
public double BestLap
{
get { return bestLap; }
set
{
bestLap = value;
OnPropertyChanged("BestLap");
}
}
private int startNr;
public int StartNr
{
get { return startNr; }
set
{
startNr = value;
OnPropertyChanged("StartNr");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
ViewModel.cs:
public class DriverViewModel
{
public ObservableCollection<Driver> DriverList { get; set; }
public DriverViewModel()
{
DriverList = new ObservableCollection<Driver>();
}
}
的視圖(MainWindow.xaml):
<Window.Resources>
<CollectionViewSource x:Key="CvsDriver"
Source="{Binding DriverList}"
IsLiveSortingRequested="True">
<CollectionViewSource.SortDescriptions>
<componentModel:SortDescription PropertyName="BestLap" Direction="Ascending" />
</CollectionViewSource.SortDescriptions>
</CollectionViewSource>
<Style x:Key="DriverListBoxItemContainerStyle" TargetType="{x:Type ListBoxItem}">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
<Setter Property="VerticalContentAlignment" Value="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
<Setter Property="Padding" Value="2,0,0,0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
<StackPanel Height="Auto" Orientation="Horizontal">
<TextBlock TextWrapping="Wrap" Text="{Binding BestLap, StringFormat=\{0:F2\}}"/>
<TextBlock TextWrapping="Wrap" Text="{Binding StartNr}" Margin="8,0,0,0"/>
<TextBlock TextWrapping="Wrap" Text="{Binding Name}" Margin="8,0,0,0"/>
</StackPanel>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/>
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="true"/>
<Condition Property="Selector.IsSelectionActive" Value="false"/>
</MultiTrigger.Conditions>
<Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightBrushKey}}"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightTextBrushKey}}"/>
</MultiTrigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<ListBox ItemsSource="{Binding Source={StaticResource CvsDriver}}"
ItemContainerStyle="{DynamicResource DriverListBoxItemContainerStyle}" />
</Grid>
最後的主窗口。CS
public partial class MainWindow : Window
{
private readonly DriverViewModel driverViewModel;
public MainWindow()
{
// Timer generating random BestLap double values from 1.0 to 4.0 every 5 seconds
DispatcherTimer randomlyUpdateDriverBestLapTimer = new DispatcherTimer();
randomlyUpdateDriverBestLapTimer.Interval = TimeSpan.FromSeconds(5);
randomlyUpdateDriverBestLapTimer.Tick += RandomlyUpdateDriverBestLapTimerOnTick;
driverViewModel = new DriverViewModel();
Driver driver = new Driver { BestLap = 1.2, Name = "Meyer", StartNr = 1 };
driverViewModel.DriverList.Add(driver);
driver = new Driver { BestLap = 1.4, Name = "Sand", StartNr = 2 };
driverViewModel.DriverList.Add(driver);
driver = new Driver { BestLap = 1.5, Name = "Huntelaar", StartNr = 3 };
driverViewModel.DriverList.Add(driver);
this.DataContext = driverViewModel;
InitializeComponent();
randomlyUpdateDriverBestLapTimer.Start();
}
private void RandomlyUpdateDriverBestLapTimerOnTick(object sender, EventArgs eventArgs)
{
// Important to declare Random object not in the loop because it will generate the same random double for each driver
Random random = new Random();
foreach (var driver in driverViewModel.DriverList)
{
// Random double from 1.0 - 4.0 (Source code from https://stackoverflow.com/questions/1064901/random-number-between-2-double-numbers)
driver.BestLap = random.NextDouble() * (4.0 - 1.0) + 1.0;
}
}
您已經實現了你的視圖模型INotifyPropertyChanged接口?......表現出一定的代碼,如果你能... – 2014-12-04 08:35:51