Silverlight 更新对象上的ObservableCollection属性已更改
希望有人能帮我解决这个问题。我正在创建一个用于编辑图像的Silverlight应用程序。用户有一个项目,其中包含包含元素的图层。元素是文本和图像元素 我有一个代表这个项目的类。它包含一个ObservableCollection,每个层都有一个ObservableCollection。元素是一个抽象类。有一个从元素继承的TextElement和ImageElement类 我的问题是,当我更改集合中的元素时,UI永远不会更新。我在我的所有属性上使用INotifyPropertyChanged,并在集合上捕获CollectionChanged,但仍然没有成功。ObservableCollection的CollectionChanged事件在其一个元素的更新中从未被命中 这是我最初拥有的代码:Silverlight 更新对象上的ObservableCollection属性已更改,silverlight,data-binding,observablecollection,inotifypropertychanged,Silverlight,Data Binding,Observablecollection,Inotifypropertychanged,希望有人能帮我解决这个问题。我正在创建一个用于编辑图像的Silverlight应用程序。用户有一个项目,其中包含包含元素的图层。元素是文本和图像元素 我有一个代表这个项目的类。它包含一个ObservableCollection,每个层都有一个ObservableCollection。元素是一个抽象类。有一个从元素继承的TextElement和ImageElement类 我的问题是,当我更改集合中的元素时,UI永远不会更新。我在我的所有属性上使用INotifyPropertyChanged,并在集
void Elements_CollectionChanged(
object sender,
System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{ this.NotifyChange("Elements"); }
这是绑定:
<!-- Workspace -->
<ScrollViewer Grid.Column="1" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto" Margin="5" DataContext="{Binding Project}">
<Canvas x:Name="Canvas" Background="LightGray" Width="{Binding Path=CanvasWidth}" Height="{Binding Path=CanvasHeight}">
<ItemsControl ItemsSource="{Binding Path=Layers, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<ItemsControl ItemsSource="{Binding Path=Elements, Mode=OneWay}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Background="{Binding Path=BackgroundColor}"
Visibility="{Binding Path=Visible, Converter={StaticResource BoolConverter}}"
Opacity="{Binding Path=Opacity}"
Width="{Binding ElementName=Canvas, Path=DataContext.CanvasWidth}"
Height="{Binding ElementName=Canvas, Path=DataContext.CanvasHeight}">
</Canvas>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Canvas>
<ContentControl Content="{Binding Converter={StaticResource ElementConverter}}"
Canvas.Top="{Binding Path=Top, Mode=TwoWay}"
Canvas.Left="{Binding Path=Left, Mode=TwoWay}"
Opacity="{Binding Path=Opacity}"
MouseLeftButtonDown="ContentControl_MouseLeftButtonDown">
<interactivity:Interaction.Behaviors>
<behaviors:DragInCanvasBehavior />
</interactivity:Interaction.Behaviors>
</ContentControl>
</Canvas>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Canvas>
</ScrollViewer>
这是包含到集合的类:
public class Layer : BaseBLL
{
private int numberOfElements;
#region Properties
public int Order
{
get { return this.GetValue<int>("Order"); }
set { this.SetValue<int>("Order", value); }
}
public string BackgroundColor
{
get { return this.GetValue<string>("BackgroundColor"); }
set { this.SetValue<string>("BackgroundColor", value); }
}
public double Opacity
{
get { return this.GetValue<double>("Opacity"); }
set { this.SetValue<double>("Opacity", value); }
}
public bool Visible
{
get { return this.GetValue<bool>("Visible"); }
set { this.SetValue<bool>("Visible", value); }
}
public ObservableCollection<Element> Elements { get; set; }
public Element SelectedElement
{
get { return this.GetValue<Element>("SelectedElement"); }
set { this.SetValue<Element>("SelectedElement", value); }
}
#endregion
#region Commands
public ICommand AddTextElementCommand { get; set; }
public ICommand AddImageElementCommand { get; set; }
public ICommand DeleteElementCommand { get; set; }
public ICommand SetSelectedElementCommand { get; set; }
#endregion
#region Methods
public Layer()
:this("Untitled", 0, "#ffffff", 1, true, new ObservableCollection<Element>())
{
}
public Layer(string name, int order, string backgroundColor, double opacity, bool visible, ObservableCollection<Element> elements)
: base(name)
{
this.Order = order;
this.BackgroundColor = backgroundColor;
this.Opacity = opacity;
this.Visible = visible;
this.Elements = elements;
this.Elements.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(Elements_CollectionChanged);
this.AddTextElementCommand = new DelegateCommand(AddTextElement, CanAddTextElement);
this.AddImageElementCommand = new DelegateCommand(AddImageElement, CanAddImageElement);
this.DeleteElementCommand = new DelegateCommand(DeleteElement, CanDeleteElement);
}
private void Elements_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
foreach (Element element in e.NewItems)
element.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(element_PropertyChanged);
}
void element_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
this.NotifyChange("Elements");
}
private bool CanAddTextElement(object param) { return true; }
private void AddTextElement(object param)
{
TextElement text = new TextElement();
text.Order = this.numberOfElements;
this.Elements.Add(text);
numberOfElements++;
this.SelectedElement = text;
}
private bool CanAddImageElement(object param) { return true; }
private void AddImageElement(object param)
{
var dialog = new OpenFileDialog()
{
Filter = "Image Files (*.bmp;*.jpg;*.gif;*.png;)|*.bmp;*.jpg;*.gif;*.png;",
Multiselect = false
};
bool? userClickedOK = dialog.ShowDialog();
if (userClickedOK == true)
{
string fileName = dialog.File.Name;
FileStream stream = dialog.File.OpenRead();
var imageSource = new BitmapImage();
using (FileStream fileStream = stream)
{
imageSource.SetSource(fileStream);
byte[] data = new byte[fileStream.Length];
fileStream.Read(data, 0, data.Length);
fileStream.Flush();
fileStream.Close();
}
ImageElement img = new ImageElement();
img.Name = fileName;
img.Order = this.numberOfElements;
img.Source = imageSource;
img.Height = imageSource.PixelHeight;
img.Width = imageSource.PixelWidth;
this.Elements.Add(img);
this.numberOfElements++;
this.SelectedElement = img;
}
}
private bool CanDeleteElement(object param)
{
if (this.SelectedElement != null)
return true;
else
return false;
}
private void DeleteElement(object param)
{
throw new NotImplementedException();
}
#endregion
}
这是其中一个元素的代码:
public class TextElement : Element
{
public string Text
{
get { return this.GetValue<string>("Text"); }
set { this.SetValue<string>("Text", value); }
}
public int FontSize
{
get { return this.GetValue<int>("FontSize"); }
set { this.SetValue<int>("FontSize", value); }
}
public bool Bold
{
get { return this.GetValue<bool>("Bold"); }
set { this.SetValue<bool>("Bold", value); }
}
public bool Italic
{
get { return this.GetValue<bool>("Italic"); }
set { this.SetValue<bool>("Italic", value); }
}
public string Color
{
get { return this.GetValue<string>("Color"); }
set { this.SetValue<string>("Color", value); }
}
public FontFamily Font
{
get { return this.GetValue<FontFamily>("Font"); }
set { this.SetValue<FontFamily>("Font", value); }
}
public TextElement()
: this("Untitled", 1, 5, 5, 0, 0, 0, "New text", 12, false, false, "#aaaaaa", new FontFamily("Arial"))
{
}
public TextElement(string name, double opacity, double top, double left, double rotateAngle, double centerX, double centerY,
string text, int fontSize, bool bold, bool italic, string color, FontFamily font)
: base(name, opacity, top, left, rotateAngle, centerX, centerY)
{
this.Text = text;
this.FontSize = fontSize;
this.Bold = bold;
this.Italic = italic;
this.Color = color;
this.Font = font;
}
}
如果有人能帮助我,我将不胜感激。您是否从SetValue内部触发PropertyChanged事件? 否则,应该为元素的每个属性执行此操作
public string Text
{
get { return this.GetValue<string>("Text"); }
set { this.SetValue<string>("Text", value); this.InvokePropertyChanged("Text"); }
}
private void InvokePropertyChanged( string propertyName )
{
if( this.PropertyChanged != null )
this.PropertyChanged( this, new PropertyChangedEventArgs( propertyName ) );
}
但是您是否将elements集合绑定到UI中的控件?如果是的话,你能邮寄你的装订吗?另外,您可以发布元素代码吗?元素是否实现INotifyPropertyChanged?是的,我的所有对象都实现INotifyPropertyChanged
public string Text
{
get { return this.GetValue<string>("Text"); }
set { this.SetValue<string>("Text", value); this.InvokePropertyChanged("Text"); }
}
private void InvokePropertyChanged( string propertyName )
{
if( this.PropertyChanged != null )
this.PropertyChanged( this, new PropertyChangedEventArgs( propertyName ) );
}