【www.bbyears.com--Silverlight】
文 Silverlight 版本:4.0。
首先定义数据类型,此文始终使用此定义类型。 view sourceprint?1
public
class
SimpleData : ViewModelBase
2
{
3
private
string
_text;
4
private
int
_column, _row;
5
6
public
string
Text {
get
{
return
_text; }
set
{ _text = value; OnPropertyChanged(
"Text"
); } }
7
public
int
Column {
get
{
return
_column; }
set
{ _column = value; OnPropertyChanged(
"Column"
); } }
8
public
int
Row {
get
{
return
_row; }
set
{ _row = value; OnPropertyChanged(
"Row"
); } }
9
}
前台代码:
view sourceprint?
01
<
Grid
x:Name
=
"LayoutRoot"
Background
=
"White"
>
02
<
ItemsControl
ItemsSource
=
"{Binding}"
>
03
<
ItemsControl.ItemTemplate
>
04
<
DataTemplate
>
05
<
TextBox
Text
=
"{Binding Text}"
06
Foreground
=
"Green"
07
Grid.Row
=
"{Binding Row}"
08
Grid.Column
=
"{Binding Column}"
09
Height
=
"30"
Width
=
"150"
10
/>
11
DataTemplate
>
12
ItemsControl.ItemTemplate
>
13
<
ItemsControl.ItemsPanel
>
14
<
ItemsPanelTemplate
>
15
<
Grid
ShowGridLines
=
"True"
>
16
<
Grid.RowDefinitions
>
17
<
RowDefinition
/>
18
<
RowDefinition
/>
19
<
RowDefinition
/>
20
Grid.RowDefinitions
>
21
<
Grid.ColumnDefinitions
>
22
<
ColumnDefinition
/>
23
<
ColumnDefinition
/>
24
Grid.ColumnDefinitions
>
25
Grid
>
26
ItemsPanelTemplate
>
27
ItemsControl.ItemsPanel
>
28
ItemsControl
>
29
Grid
>
后台代码:
view sourceprint?
01
public partial class MainPage : UserControl
02
{
03
public MainPage()
04
{
05
InitializeComponent();
06
this.DataContext = new SimpleData[]
07
{
08
new SimpleData{ Text = "111111", Column = 0, Row = 0 },
09
new SimpleData{ Text = "222222", Column = 1, Row = 1 },
10
new SimpleData{ Text = "333333", Column = 0, Row = 2 },
11
};
12
}
13
}
可以看出这段代码的本意是通过绑定的方式设置,在 ItemsControl 里面显示 3 个 TextBox,同时指定了相应在 Grid 的行和列。
但是,你懂的!
这样的代码肯定是不能正确运行。特别是在Silverlight。
如果这是在 WPF 环境,很庆幸你还可以用 ItemContainerStyle 搞定:
view sourceprint?
1
<
ItemsControl.ItemContainerStyle
>
2
<
Style
>
3
<
Setter
Property
=
"Grid.Row"
Value
=
"{Binding Row, Mode=OneWay}"
/>
4
<
Setter
Property
=
"Grid.Column"
Value
=
"{Binding Column, Mode=OneWay}"
/>
5
Style
>
6
ItemsControl.ItemContainerStyle
>
只可惜这是在 Silverlight 环境。我们只能够想别的办法了。
为什么不可以?拿出 Silverlight Spy 或者 Snoop 查看相应的 VisualTree。可以看到在 TextBox 外面还套了一个 ContextPresenter。
于是我们可以想到,能不能设置 ContextPresenter 的 Grid.Row 和 Grid.Colume 达到控制行列的目的?
于是我们得到下面的思路,使用附加属性把相应的绑定关系提升。
view sourceprint?
001
using
System;
002
using
System.Collections.Generic;
003
using
System.Globalization;
004
using
System.Linq;
005
using
System.Reflection;
006
using
System.Windows;
007
using
System.Windows.Controls;
008
using
System.Windows.Data;
009
using
System.Windows.Media;
010
011
namespace
Delay
012
{
013
public
class
UpUp : DependencyObject
014
{
015
// Using a DependencyProperty as the backing store for Up. This enables animation, styling, binding, etc...
016
public
static
readonly
DependencyProperty UpProperty =
017
DependencyProperty.RegisterAttached(
"Up"
,
typeof
(
string
),
typeof
(UpUp),
new
PropertyMetadata(
string
.Empty));
018
019
public
static
void
SetUp(FrameworkElement element,
string
value)
020
{
021
HanderClosure hander = element.GetValue(UpProperty)
as
HanderClosure;
022
if
(hander ==
null
)
023
{
024
hander =
new
HanderClosure(element, value);
025
element.SetValue(UpProperty, value);
026
element.LayoutUpdated +=
new
EventHandler(hander.element_LayoutUpdated);
027
}
028
}
029
public
static
string
GetUp(FrameworkElement element)
030
{
031
HanderClosure hander = element.GetValue(UpProperty)
as
HanderClosure;
032
if
(hander ==
null
)
033
return
null
;
034
else
035
return
hander.OrgParamenter;
036
}
037
038
private
class
HanderClosure
039
{
040
private
FrameworkElement _elem =
null
;
041
private
string
[] propertys =
null
;
042
private
int
_level;
043
private
UpMode _mode;
044
private
string
_orgParamenter;
045
046
public
string
OrgParamenter {
get
{
return
_orgParamenter; } }
047
048
public
HanderClosure(FrameworkElement element,
string
parameter)
049
{
050
if
(element ==
null
)
051
throw
new
ArgumentNullException(
"element"
);
052
if
(parameter ==
null
)
053
throw
new
ArgumentNullException(
"parameter"
);
054
_elem = element;
055
_level = 1;
056
_mode = UpMode.Copy;
057
_orgParamenter = parameter;
058
059
string
[] array = parameter.Split(
new
char
[] {
";"
}, StringSplitOptions.RemoveEmptyEntries);
060
if
(array.Length == 0)
061
throw
new
ArgumentException(
"parameter"
);
062
propertys = array[0].Split(
new
char
[] {
","
}, StringSplitOptions.RemoveEmptyEntries);
063
if
(array.Length > 1)
064
{
065
int
num;
066
if
(
int
.TryParse(array[1].Trim(),
out
num))
067
{
068
_level = num;
069
}
070
}
071
if
(array.Length > 2)
072
{
073
UpMode mode;
074
if
(Enum.TryParse(array[2].Trim(),
true
,
out
mode))
075
{
076
_mode = mode;
077
}
078
}
079
}
080
081
public
void
element_LayoutUpdated(
object
sender, EventArgs e)
082
{
083
FrameworkElement parent = _elem;
084
for
(
int
i = 0; i < _level && parent !=
null
; i++)
085
{
086
parent = VisualTreeHelper.GetParent(parent)
as
FrameworkElement;
087
}
088
if
(parent ==
null
)
089
return
;
090
091
foreach
(
string
property
in
propertys)
092
{
093
Apply(_elem, parent, property.Trim());
094
}
095
}
096
097
// Copyright (C) Microsoft Corporation. All Rights Reserved.
098
// This code released under the terms of the Microsoft Public License
099
// (Ms-PL, http://opensource.org/licenses/ms-pl.html).
100
private
void
Apply(FrameworkElement element1, FrameworkElement element2,
string
property)
101
{
102
var array = property.Split(
"."
);
103
if
(array.Length != 2)
104
throw
new
ArgumentException(
"property"
);
105
string
typeName = array[0].Trim();
106
string
propertyName = array[1].Trim();
107
108
Type type =
null
;
109
foreach
(var assembly
in
AssembliesToSearch)
110
{
111
// Match on short or full name
112
type = assembly.GetTypes()
113
.Where(t => (t.FullName == typeName) || (t.Name == typeName))
114
.FirstOrDefault();
115
if
(type !=
null
)
116
break
;
117
}
118
if
(
null
== type)
119
{
120
// Unable to find the requested type anywhere
121
throw
new
ArgumentException(
122
string
.Format(
123
CultureInfo.CurrentCulture,
124
"Unable to access type "{0}". Try using an assembly qualified type name."
,
125
typeName));
126
&n