在我的应用程序中,我有一个使用ObservableCollection作为ImageSource的网格 我的模型看起来像这样:
public class Student:INotifyPropertyChanged
{
public Student()
{
}
public Student(int id, string firstName, string lastName, int points, bool active = true)
{
_id = id;
_firstName = firstName;
_lastName = lastName;
_points = points;
_active = active;
}
private int _id;
private string _firstName;
private string _lastName;
private int _points;
private bool _active;
public int Id
{
get { return _id; }
set
{
if (value == _id) return;
_id = value;
OnPropertyChanged();
}
}
public string FirstName
{
get { return _firstName; }
set
{
if (value == _firstName) return;
_firstName = value;
OnPropertyChanged();
}
}
public string LastName
{
get { return _lastName; }
set
{
if (value == _lastName) return;
_lastName = value;
OnPropertyChanged();
}
}
public string Name
{
get { return string.Format("{0} {1}", _firstName, _lastName); }
}
public int Points
{
get { return _points; }
set
{
if (value == _points) return;
_points = value;
OnPropertyChanged();
}
}
public string Avatar
{
get
{
string appPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
if (appPath == null) return null;
string imagesPath = Path.Combine(appPath, "Images","Students");
if (!Directory.Exists(imagesPath)) return null;
var imagePath = Path.Combine(imagesPath, string.Format("{0}.png", _id));
if (File.Exists(imagePath)) return imagePath;
imagePath = Path.Combine(imagesPath, string.Format("{0}.jpg", _id));
if (File.Exists(imagePath)) return imagePath;
imagePath = Path.Combine(imagesPath, string.Format("{0}.jpeg", _id));
if (File.Exists(imagePath)) return imagePath;
return Path.Combine(imagesPath, "Default.png");
}
}
public bool Active
{
get { return _active; }
set
{
if (value == _active) return;
_active = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
我还将所选学生从网格中存储在变量中 我的XAML看起来像这样:
<DataGrid
Grid.Column="0"
Name="StudentsGrid"
ItemsSource="{Binding Students}"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
CanUserAddRows="True"
AutoGenerateColumns="False"
RowEditEnding="StudentsGrid_OnRowEditEnding"
SelectedItem="{Binding SelectedStudent, Converter={StaticResource SelectedStudentConverter}}">
<DataGrid.Columns>
<DataGridTextColumn Width="*" Binding="{Binding FirstName, UpdateSourceTrigger=PropertyChanged}" ClipboardContentBinding="{x:Null}" Header="Imię"/>
<DataGridTextColumn Width="*" Binding="{Binding LastName, UpdateSourceTrigger=PropertyChanged}" ClipboardContentBinding="{x:Null}" Header="Nazwisko"/>
<DataGridCheckBoxColumn Width="60" Binding="{Binding Active, UpdateSourceTrigger=PropertyChanged}" ClipboardContentBinding="{x:Null}" Header="Aktywna"/>
</DataGrid.Columns>
</DataGrid>
<Border HorizontalAlignment="Left" Height="120" Margin="10,78,0,0"
VerticalAlignment="Top" Width="97" BorderBrush="Black" BorderThickness="1">
<Image Name="Avatar" Source="{Binding SelectedStudent.Avatar, Converter={StaticResource AvatarConverter}}" />
</Border>
<Button Click="ButtonBase_OnClick" Content="Change avatar" Grid.Column="1" HorizontalAlignment="Right" Margin="0,80,10,0" VerticalAlignment="Top" Width="107"/>
我已经为选定的学生使用了转换器,因为我在尝试添加新行时在网格周围出现红色边框。
和负责按钮点击的代码:
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
Microsoft.Win32.OpenFileDialog openfile = new Microsoft.Win32.OpenFileDialog
{
DefaultExt = "*.png",
Filter = "JPG (*.jpg,*.jpeg)|*.jpg;*.jpeg|PNG (*.png)|*.png"
};
bool? result = openfile.ShowDialog();
if (result == true)
{
var source = openfile.FileName;
var ext = Path.GetExtension(source);
string appPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
if (appPath == null) return;
string imagesPath = Path.Combine(appPath, "Images","Students");
if (!Directory.Exists(imagesPath)) Directory.CreateDirectory(imagesPath);
var destination = Path.Combine(imagesPath, string.Format("{0}{1}", _selectedStudent.Id, ext));
Student old = _selectedStudent;
SelectedStudent = null;
File.Copy(source, destination,true);
SelectedStudent = old;
var bindingExpression = Avatar.GetBindingExpression(Image.SourceProperty);
if (bindingExpression != null) bindingExpression.UpdateTarget();
}
}
和AvatarConverter:
public class AvatarConverter:IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
try
{
BitmapImage image = new BitmapImage();
image.BeginInit();
image.CacheOption = BitmapCacheOption.OnLoad;
image.UriSource = new Uri((string)value);
image.EndInit();
return image;
//I've used below code previously, but file was locked
return new BitmapImage(new Uri((string)value));
}
catch
{
return new BitmapImage();
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
我的想法是显示存储在Images\Student
内的当前头像。如果文件存在,则Avatar
属性设置为该图像路径,否则我显示Default.png
。
在当前所选的头像图片旁边,我添加了一个按钮,可让我更新头像。
我无法替换图像文件,因为它正在使用中,但感谢this answer我能够快速解决这个问题。
但我无法更新应用内的图片以显示新来源。我尝试过SelectedStudent
并恢复原状,但没有运气。