Вы пытаетесь запрограммировать приложение WPF так же, как приложение Windows Forms. Поверьте, вы сможете достичь своей цели намного проще, если вы действительно изучите некоторые шаблоны разработки WPF (например, MVVM ).
Например, это может быть легко достигнуто с помощью ObservableCollection , содержащего все (не знаю, как вы это делаете) FileInfo экземпляров (по одному для каждого файла).
Затем вы связываете a ItemsControl ItemsSource свойство с этой коллекцией. Теперь, всякий раз, когда вы добавляете новый экземпляр FileInfo в ObservableCollection, ItemsControl будет добавлять новую строку и связывать эту строку с экземпляром.
Конечно, шаблон по умолчанию для каждой строки просто вызывает .ToString () для каждого экземпляра, поэтому вы получите набор строк, содержащий "System.IO.FileInfo" . Чтобы отобразить информацию о каждом FileInfo, вы можете добавить DataTemplate в ItemsSource.ItemTemplate и добавить элементы управления, которые привязываются к открытым свойствам FileInfo.
ОЧЕНЬ важно понимать некоторые из этих базовых шаблонов при разработке приложений WPF. ОЧЕНЬ СЛОЖНО пытаться взаимодействовать с пользовательским интерфейсом из кода, как вы пытаетесь. Многие шаблоны пользовательского интерфейса для приложений WPF оптимизированы для использования в XAML; попытка взаимодействия с ними (например, с прикрепленными свойствами) из кода может быть чрезвычайно запутанной и нелогичной.
Вот простой пример MVVM, который я обновил. Чтобы использовать это, создайте новое решение (3.5 или выше) под названием SimpleMVVM . Создайте новый класс в корне проекта с именем ViewModel и добавьте в файл следующий код:
/// <summary>
/// A simple ViewModel to demonstrate MVVM
/// </summary>
public sealed class ViewModel : DependencyObject, IDataErrorInfo
{
#region Properties
#region DirectoryName
/// <summary>
/// The <see cref="DependencyProperty"/> for <see cref="DirectoryName"/>.
/// </summary>
public static readonly DependencyProperty DirectoryNameProperty =
DependencyProperty.Register(
DirectoryNameName,
typeof(string),
typeof(ViewModel),
new UIPropertyMetadata(null));
/// <summary>
/// The name of the <see cref="DirectoryName"/> <see cref="DependencyProperty"/>.
/// </summary>
public const string DirectoryNameName = "DirectoryName";
/// <summary>
///
/// </summary>
public object DirectoryName
{
get { return (object)GetValue(DirectoryNameProperty); }
set { SetValue(DirectoryNameProperty, value); }
}
#endregion
#region SelectedFile
/// <summary>
/// The <see cref="DependencyProperty"/> for <see cref="SelectedFile"/>.
/// </summary>
public static readonly DependencyProperty SelectedFileProperty =
DependencyProperty.Register(
SelectedFileName,
typeof(FileInfo),
typeof(ViewModel),
new UIPropertyMetadata(null));
/// <summary>
/// The name of the <see cref="SelectedFile"/> <see cref="DependencyProperty"/>.
/// </summary>
public const string SelectedFileName = "SelectedFile";
/// <summary>
///
/// </summary>
public FileInfo SelectedFile
{
get { return (FileInfo)GetValue(SelectedFileProperty); }
set { SetValue(SelectedFileProperty, value); }
}
#endregion
/// <summary>
/// The files found under <see cref="DirectoryName"/>.
/// </summary>
public ObservableCollection<FileInfo> Files { get; private set; }
/// <summary>
/// Holds the last filename error for IDataErrorInfo
/// </summary>
private string _lastDirectoryNameError = null;
#endregion
#region ctor
/// <summary>
/// Initializes a new instance of the <see cref="ViewModel"/> class.
/// </summary>
public ViewModel()
{
Files = new ObservableCollection<FileInfo>();
}
#endregion
#region methods
/// <summary>
/// Invoked whenever the effective value of any dependency property on this <see cref="T:System.Windows.DependencyObject"/> has been updated. The specific dependency property that changed is reported in the event data.
/// </summary>
/// <param name="e">Event data that will contain the dependency property identifier of interest, the property metadata for the type, and old and new values.</param>
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
{
base.OnPropertyChanged(e);
if (e.Property == DirectoryNameProperty)
UpdateFiles(e.OldValue as string, e.NewValue as string);
}
/// <summary>
/// Updates <see cref="Files"/> when <see cref="DirectoryName"/> changes.
/// </summary>
/// <param name="oldDirectoryName">The old value of <see cref="DirectoryName"/></param>
/// <param name="newDirectoryName">The new value of <see cref="DirectoryName"/></param>
private void UpdateFiles(string oldDirectoryName, string newDirectoryName)
{
if (string.IsNullOrWhiteSpace(newDirectoryName))
{
Files.Clear();
return;
}
if (!string.IsNullOrEmpty(oldDirectoryName) &&
oldDirectoryName.Equals(newDirectoryName, StringComparison.OrdinalIgnoreCase))
return;
try
{
var di = new DirectoryInfo(Directory.Exists(newDirectoryName) ? newDirectoryName : Path.GetDirectoryName(newDirectoryName));
// dirty hack
if (di.ToString().Equals(".", StringComparison.OrdinalIgnoreCase))
{
_lastDirectoryNameError = "Not a valid directory name.";
return;
}
Files.Clear();
foreach (var file in di.GetFiles())
Files.Add(file);
_lastDirectoryNameError = null;
}
catch (Exception ioe)
{
_lastDirectoryNameError = ioe.Message;
}
}
#endregion
#region IDataErrorInfo
/// <summary>
/// Gets an error message indicating what is wrong with this object.
/// </summary>
/// <returns>An error message indicating what is wrong with this object. The default is an empty string ("").</returns>
string IDataErrorInfo.Error
{
get
{
return _lastDirectoryNameError;
}
}
/// <summary>
/// Gets the error message for the property with the given name.
/// </summary>
/// <returns>The error message for the property. The default is an empty string ("").</returns>
string IDataErrorInfo.this[string columnName]
{
get
{
if (columnName.Equals(DirectoryNameName, StringComparison.OrdinalIgnoreCase))
return _lastDirectoryNameError;
return null;
}
}
#endregion
}
Далее откройте MainWindow.xaml и замените xaml следующим:
<Window
x:Class="SimpleMVVM.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:t="clr-namespace:SimpleMVVM"
Title="MainWindow"
Height="350"
Width="525">
<Window.DataContext>
<t:ViewModel />
</Window.DataContext>
<Window.Resources>
<Style
x:Key="alternatingListViewItemStyle"
TargetType="{x:Type ListViewItem}">
<Style.Triggers>
<Trigger
Property="ItemsControl.AlternationIndex"
Value="1">
<Setter
Property="Background"
Value="LightGray"></Setter>
</Trigger>
<Trigger
Property="ItemsControl.AlternationIndex"
Value="2">
<Setter
Property="Background"
Value="White"></Setter>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition
Height="auto" />
<RowDefinition />
<RowDefinition
Height="auto" />
</Grid.RowDefinitions>
<TextBox
Margin="4"
Text="{Binding DirectoryName, ValidatesOnDataErrors=True, ValidatesOnExceptions=True,UpdateSourceTrigger=PropertyChanged}">
<TextBox.Style>
<Style
TargetType="TextBox">
<Setter
Property="ToolTip"
Value="Please enter a directory name" />
<Style.Triggers>
<Trigger
Property="Validation.HasError"
Value="true">
<Setter
Property="ToolTip"
Value="{Binding (Validation.Errors)[0].ErrorContent, RelativeSource={x:Static RelativeSource.Self}}" />
</Trigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
<ListView
Margin="4"
Grid.Row="1"
AlternationCount="2"
ItemsSource="{Binding Files}"
ItemContainerStyle="{StaticResource alternatingListViewItemStyle}"
SelectedItem="{Binding SelectedFile}">
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition
Width="100" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Label
Grid.Row="0">Name</Label>
<Label
Grid.Row="1">Size</Label>
<Label
Grid.Row="2">Read Only</Label>
<Label
Grid.Row="3">Type</Label>
<TextBlock
Grid.Row="0"
Grid.Column="1"
Text="{Binding Name}" />
<TextBlock
Grid.Row="1"
Grid.Column="1"
Text="{Binding Length}" />
<CheckBox
Grid.Row="2"
Grid.Column="1"
IsChecked="{Binding IsReadOnly}"
IsEnabled="False" />
<TextBlock
Grid.Row="3"
Grid.Column="1"
Text="{Binding Extension}" />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<StatusBar
Grid.Row="2">
<StatusBarItem
Content="{Binding SelectedFile.FullName, StringFormat='Selected: {0}', FallbackValue='Please enter a directory and select a file.'}" />
</StatusBar>
</Grid>
</Window>
(простите меня за дамп кода!) Скомпилируйте, исправьте ошибки и запустите.