我有两个用户控件,一个是简单的图片持有者,里面有一个复选框。另一个用作容器而不是前一个控件的集合。
所以 HorizontalPictureScroller 可以有很多 SelectablePicture 控件。我会粘贴每个控件的小代码:
首先, HorizontalPictureScroller :
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Collections.ObjectModel;
namespace WinformsPlayground
{
[Serializable()]
public partial class HorizontalPictureScroller : UserControl
{
public HorizontalPictureScroller()
{
InitializeComponent();
Pictures = new ObservableCollection<SelectablePicture>();
Pictures.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(Pictures_CollectionChanged);
}
#region "Properties"
public ObservableCollection<SelectablePicture> Pictures { get; set; }
private int PositionControlX = 0;
#endregion
#region "Methods"
private void RedrawPictures()
{
PositionControlX = 0;
foreach (var picture in Pictures)
{
picture.Location = new Point(PositionControlX + panelPicturesWrapper.AutoScrollPosition.X, 0);
PositionControlX += 130;
panelPicturesWrapper.Controls.Add(picture);
}
}
public void AddPicture(SelectablePicture picture)
{
Pictures.Add(picture);
}
public void RemovePicture(SelectablePicture picture)
{
Pictures.Remove(picture);
}
public void MovePictureLeft(int index)
{
SelectablePicture tmpPicture = Pictures[index];
Pictures[index] = Pictures[index - 1];
Pictures[index - 1] = tmpPicture;
}
public void MovePictureRight(int index)
{
SelectablePicture tmpPicture = Pictures[index];
Pictures[index] = Pictures[index + 1];
Pictures[index + 1] = tmpPicture;
}
#endregion
#region "Events"
void Pictures_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
RedrawPictures();
}
#endregion
}
}
现在, SelectablePicture 控件:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WinformsPlayground
{
[Serializable()]
public partial class SelectablePicture : UserControl
{
public SelectablePicture()
{
InitializeComponent();
panel1.BackgroundImageLayout = ImageLayout.Zoom;
}
public SelectablePicture(Image image)
{
panel1.BackgroundImage = image;
panel1.BackgroundImageLayout = ImageLayout.Zoom;
}
#region "Properties"
public Image Image()
{
return panel1.BackgroundImage;
}
public bool IsSelected()
{
return chkSelected.Checked;
}
#endregion
#region "Methods"
public void ToggleCheckBox()
{
chkSelected.Checked = chkSelected.Checked ? false : true;
}
public void VisuallySelect()
{
this.BackColor = Color.FromArgb(51, 153, 255);
}
public void VisuallyDeselect()
{
//If none of the controls inside the usercontrol have focus, set this control to white.
if (!this.Focused && !this.panel1.Focused && !this.chkSelected.Focused)
{
this.BackColor = Color.White;
}
}
#endregion
#region "Events"
private void panel1_Click(object sender, EventArgs e)
{
VisuallySelect();
ToggleCheckBox();
panel1.Focus();
}
private void chkSelected_Click(object sender, EventArgs e)
{
VisuallySelect();
ToggleCheckBox();
chkSelected.Focus();
}
private void SelectablePicture_Click(object sender, EventArgs e)
{
VisuallySelect();
ToggleCheckBox();
this.Focus();
}
private void panel1_Leave(object sender, EventArgs e)
{
VisuallyDeselect();
}
private void chkSelected_Leave(object sender, EventArgs e)
{
VisuallyDeselect();
}
private void SelectablePicture_Leave(object sender, EventArgs e)
{
VisuallyDeselect();
}
#endregion
}
}
这是我在尝试将HorizontalPictureScroller拖到我的Winform设计视图时得到的错误的屏幕截图(抱歉,我无法在此处粘贴文本):
我的用户控件非常简单,我无法看到代码中出现了什么问题。
也许这对我来说是一个明显的错误。 :P非常感谢你的时间。
答案 0 :(得分:1)
由于您使用的是SerializableAttribute
,但正在抛出异常,但UserControl
没有。
来自SerializableAttribute
的文档:
如果要序列化的对象图中的任何类型没有应用SerializableAttribute属性,则公共语言运行库会抛出SerializationException。
答案 1 :(得分:0)
似乎UserControl SelectablePicture需要序列化,因为它在Collection中使用。所以你在attribut [Serializable()]的解决方案附近。但是你最好在UserControl SelectablePicture中实现ISerializable接口
public partial class SelectablePicture : UserControl, ISerializable
{
#region ISerializable Membres
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
...
}
#endregion
}
这是解决问题的第一步。这样,拖放UserControl时就不会出现错误消息。但现在你必须管理序列化。
如果有人知道为什么需要序列化,我很感兴趣。