Вы хотите, чтобы элементы пользовательского интерфейса имели хороший опыт разработки (в том числе в Blend). Это звучит как разумная цель.
Давайте посмотрим, что такое элемент пользовательского интерфейса. В остальной части этого ответа я буду называть это контролем. Ответственность элемента управления заключается в отображении пользовательского интерфейса и реагировании на пользовательские события. Поскольку оно должно иметь поведение, оно должно иметь только поведение, связанное с отображением пользовательского интерфейса и пользовательскими событиями.
Кроме того, сама структура (Silverlight, а также WPF) налагает правило: все элементы управления должны иметь конструктор по умолчанию. Кроме того, поскольку DataContext
является свойством, присваивать его необязательно.
Мы должны помнить об инкапсуляции. Любой элемент управления, который мы разрабатываем, должен хорошо работать в рамках ограничений, указанных выше. Это означает, что, кроме конструктора по умолчанию, он также должен работать правильно без DataContext . Другими словами, опыт Blendability должен предоставляться самим элементом управления, а не внешним контейнером, который необходимо загрузить для присвоения DataContext
.
Когда элемент управления должен реагировать на пользовательские события, я всегда находил интерфейс ICommand
более чем достаточным. Присоедините ICommands
к любому подходящему обработчику событий в элементе управления. ICommands
определены моделью представления, но прелесть ICommand
заключается в том, что это в основном пустой метод, который означает, что тривиально предоставить (по умолчанию) локальное значение по умолчанию в случае, когда DataContext
равно нулю , Однако это редко требуется, поскольку команды не вызываются командами.
Вот пример из моей книги :
<Window x:Class="Ploeh.Samples.ProductManagement.WpfClient.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Product Management"
Height="300"
Width="300"
MinHeight="300"
MinWidth="300">
<Window.Resources>
<Style x:Key="ProductStyle" TargetType="{x:Type ListViewItem}">
<Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay}" />
</Style>
</Window.Resources>
<DockPanel FocusManager.FocusedElement="{Binding ElementName=productsListView}">
<Menu DockPanel.Dock="Top">
<MenuItem Header="_File">
<Separator />
<MenuItem Header="E_xit" Command="{Binding Path=CloseCommand}" />
</MenuItem>
<MenuItem Header="_Actions">
<MenuItem Header="_Refresh" InputGestureText="F5" Command="{Binding Path=RefreshCommand}" />
<MenuItem Header="_Add Product" InputGestureText="Ins" Command="{Binding Path=InsertProductCommand}" />
<MenuItem Header="_Edit Product" InputGestureText="Enter" Command="{Binding Path=EditProductCommand}" />
<MenuItem Header="_Delete Product" InputGestureText="Del" Command="{Binding Path=DeleteProductCommand}" />
</MenuItem>
</Menu>
<ToolBarTray DockPanel.Dock="Top" HorizontalAlignment="Stretch">
<ToolBar HorizontalAlignment="Stretch" HorizontalContentAlignment="Left">
<Button Command="{Binding Path=RefreshCommand}">Refresh</Button>
<Button Command="{Binding Path=InsertProductCommand}">Add</Button>
<Button Command="{Binding Path=EditProductCommand}">Edit</Button>
<Button Command="{Binding Path=DeleteProductCommand}">Delete</Button>
</ToolBar>
</ToolBarTray>
<ListView x:Name="productsListView" ItemContainerStyle="{StaticResource ProductStyle}" ItemsSource="{Binding Path=Products}" SelectionMode="Single">
<ListView.View>
<GridView>
<GridViewColumn Header="Id" DisplayMemberBinding="{Binding Path=Id}" />
<GridViewColumn Header="Name" DisplayMemberBinding="{Binding Path=Name}" />
<GridViewColumn Header="Price" DisplayMemberBinding="{Binding Path=UnitPrice}" />
</GridView>
</ListView.View>
</ListView>
</DockPanel>
</Window>
и код позади:
public partial class MainWindow : Window
{
public MainWindow()
{
this.InitializeComponent();
}
}