曾經總認為動態布局是個非常麻煩的問題。是個非常須要功力的問題。可是貌似在.NET中,在WPF中卻不是那么的麻煩。以下介紹我如今實現的一個動態布局的實例。
由於有需求,所以困難得克服!而我們的需求表名。不同的用戶須要的界面元素是不一樣的,我們總不能每次都去改動代碼吧!所以,須要完畢動態布局。
這里主要完畢這樣一個功能:
1、動態畫線
2、動態new控件
3、線和控件都是可拖拽並任意放置位置的
4、線和控件是可刪除的
5、控件是可綁定屬性和事件的
要完畢這種功能,我們首先得定義三個鼠標事件。即:左鍵down、move、up,右鍵刪除(不能僅僅添加不刪除啊)。
比如我要畫一條線。那么左鍵down的時候,我就須要記錄當前鼠標的位置。
左鍵down而且move的時候,要實時顯示畫出來的線。左鍵已經down而且左鍵up的時候記錄位置而且完畢畫線。
就是這樣一個過程我們就完畢了動態畫一條線。
動態生成控件就相對簡單了。有了線,有了控件。連在一起,不就完畢布局了嗎?當然是要把位置記錄下來的。
代碼上:
void Canvas_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
//true表示當前是拖拽模式
if (currentPattern == "0")
{
//推斷是否選的是主窗口
if (e.Source == mainCanvas)
{ }
else
{
_isDown = true;
_startPoint = e.GetPosition(mainCanvas);
_originalElement = e.Source as UIElement;
}
}
else if (currentPattern == "1")
{
_isDragging = true;
Canvas board = sender as Canvas;
_startPoint = e.GetPosition(board);
insertShape = CreateShape();
insertShape.Opacity = opacity / 2;
Canvas.SetLeft(insertShape, e.GetPosition(board).X); //插入線條的起點x1/y1
Canvas.SetTop(insertShape, e.GetPosition(board).Y);
board.Children.Add(insertShape);
board.RegisterName(insertShape.Name, insertShape);
}
}
void Canvas_PreviewMouseMove(object sender, MouseEventArgs e)
{
//true表示當前是拖拽模式
if (currentPattern == "0")
{
if (_isDown)
{
//假設沒有拖拽或者超出了界面
if ((_isDragging == false) && ((Math.Abs(e.GetPosition(mainCanvas).X - _startPoint.X) > SystemParameters.MinimumHorizontalDragDistance) ||
(Math.Abs(e.GetPosition(mainCanvas).Y - _startPoint.Y) > SystemParameters.MinimumVerticalDragDistance)))
{
_isDragging = true;
_originalLeft = Canvas.GetLeft(_originalElement); //獲得原元素的位置
_originalTop = Canvas.GetTop(_originalElement);
_overlayElement = new Rectangle()
{
Width = _originalElement.RenderSize.Width,
Height = _originalElement.RenderSize.Height,
Fill = new VisualBrush(_originalElement),
Opacity = 0.8 //陰影的不透明性
};
Canvas.SetLeft(_overlayElement, _originalLeft);
Canvas.SetTop(_overlayElement, _originalTop);
mainCanvas.Children.Add(_overlayElement);
}
//假設正在移動中,顯示實時位置
if (_isDragging)
{
Point CurrentPosition = Mouse.GetPosition(mainCanvas);
//設置浮動對象的位置
Canvas.SetLeft(_overlayElement, _originalLeft + CurrentPosition.X - _startPoint.X);
Canvas.SetTop(_overlayElement, _originalTop + CurrentPosition.Y - _startPoint.Y);
}
}
}
else if (currentPattern == "1")
{
Canvas board = sender as Canvas;
if (_isDragging && insertShape != null)
{
if (insertShape is Line)
{
(insertShape as Line).X1 = 0; (insertShape as Line).X2 = e.GetPosition(board).X - _startPoint.X; //設置線條的X1/Y1/X2/Y2
(insertShape as Line).Y1 = 0; (insertShape as Line).Y2 = e.GetPosition(board).Y - _startPoint.Y;
}
}
}
}
void Canvas_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
//true表示當前是拖拽模式
if (currentPattern == "0")
{
if (_isDown)
{
if (_isDragging)
{
//將陰影位置設置為當前
Canvas.SetLeft(_originalElement, Canvas.GetLeft(_overlayElement));
Canvas.SetTop(_originalElement, Canvas.GetTop(_overlayElement));
Point _positionInOverlayElement = Mouse.GetPosition(_overlayElement);
mainCanvas.Children.Remove(_overlayElement);
_overlayElement = null;
}
//將移動標識設置為 false
_isDragging = false;
_isDown = false;
}
}
else if (currentPattern == "1")
{ //假設是畫線模式。則將拖拽設置為false。將透明度還原
_isDragging = false;
if (insertShape != null)
insertShape.Opacity = opacity;
}
}
有了這三個基本的事件。你就能夠非常輕松的完畢動態布局了。怎樣保存的呢?我是把各個控件的位置放在了數據庫中。載入的時候將位置信息讀出來。
private void btnSave_Click(object sender, RoutedEventArgs e)
{
//遍歷全部的界面控件,拿到他們的位置信息,保存。
List<A> listAConfig = new List<A>();
//獲得界面上全部的Line元素
List<Line> listLine = GetElementFormUI.GetChildObjects<Line>(mainCanvas);
for (int i = 0; i < listLine.Count; i++) {
Line l = listLine[i] ;
A enAConfig = new A();
enAConfig .S_ID = DateTime.Now.ToFileTime().ToString();
enAConfig .S_NAME = l.Name;
enAConfig .S_SHAPETYPE = "Line";
enAConfig .I_LEFT =decimal.Parse(Canvas.GetLeft(l as UIElement).ToString());
enAConfig .I_TOP = decimal.Parse(Canvas.GetTop(l as UIElement).ToString());
enAConfig .I_X2 = decimal.Parse(l.X2.ToString());
enAConfig .I_Y2 = decimal.Parse(l.Y2.ToString());
listAConfig.Add(enAConfig );
}
//推斷是否保存成功
if (ServiceFactory.GetAConifgService().AddAConfig(listAConfig))
{
MessageBox.Show("保存成功。", "恭喜!", MessageBoxButton.OK);
}
else {
MessageBox.Show("保存失敗!", "警告!
", MessageBoxButton.OK);
}
}
至此,我們完畢了動態布局的設定和保存,嘗試一下吧!
