먼저 WPF 또는 다른 XAML 기반 기술과 함께 작동하려면를 이해해야합니다 그
UI is not Data. Data is Data. UI is UI.
이것은 당신이 데이터를 채울하기 위해, 코드의 모든 ComboBox
또는 다른 UI 요소를 조작하지만, 대신 ViewModel
를 생성하고 이러한 객체를 바인드되지 않게해야 함을 의미한다. 이 예에서
는
Window
이 간단한 예제이기 때문에 그 자체가
ViewModel
로 사용되지만 별도의 클래스에 모든 응용 프로그램 논리를 이동 고려해야합니다
<Window x:Class="MiscSamples.UIisNotData"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="UIisNotData" Height="300" Width="300">
<UniformGrid Rows="1" Columns="2">
<DockPanel>
<TextBlock Text="Owners:" DockPanel.Dock="Top" FontWeight="Bold" TextAlignment="Center" Margin="2"/>
<Button Content="Add" Width="80" DockPanel.Dock="Bottom" Margin="2" Click="AddOwner"/>
<ListBox ItemsSource="{Binding Owners}">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<TextBlock Text="{Binding Name}" x:Name="block"/>
<TextBox Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}" Visibility="Collapsed" x:Name="box"/>
</Grid>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType=ListBoxItem}}" Value="True">
<Setter TargetName="block" Property="Visibility" Value="Collapsed"/>
<Setter TargetName="box" Property="Visibility" Value="Visible"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DockPanel>
<DockPanel>
<TextBlock Text="Dogs:" DockPanel.Dock="Top" FontWeight="Bold" TextAlignment="Center" Margin="2"/>
<ListBox ItemsSource="{Binding Dogs}" HorizontalContentAlignment="Stretch">
<ListBox.ItemTemplate>
<DataTemplate>
<DockPanel>
<ComboBox ItemsSource="{Binding DataContext.Owners, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}"
SelectedItem="{Binding Owner}" DisplayMemberPath="Name"
DockPanel.Dock="Right" Width="100"/>
<TextBlock>
<Run Text="{Binding Name}"/>
<Run Text=", "/>
<Run Text="{Binding Kind}"/>
</TextBlock>
</DockPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DockPanel>
</UniformGrid>
</Window>
코드 뒤에 (이 코드는 배치해야)는 뷰 모델에 :
public partial class UIisNotData : Window
{
public ObservableCollection<Owner> Owners { get; set; }
public ObservableCollection<string> Kinds { get; set; }
public ObservableCollection<Dog> Dogs { get; set; }
public UIisNotData()
{
InitializeComponent();
Owners = new ObservableCollection<Owner>
{
new Owner() {Name = "Jack"},
new Owner() {Name = "Mike"},
new Owner() {Name = "Kirk"},
new Owner() {Name = "John"},
};
Kinds = new ObservableCollection<string>
{
"Affenpinscher",
"Afghan Hound",
"Airedale Terrier",
"Akita"
//.. All the rest of dog Breeds taken from http://www.petmd.com/dog/breeds?breed_list=az#.UVsQKpPcmQo
};
Dogs = new ObservableCollection<Dog>
{
new Dog() {Name = "Bobby", Kind = Kinds[0], Owner = Owners[0]},
new Dog() {Name = "Fido", Kind = Kinds[1], Owner = Owners[1]},
new Dog() {Name = "Toby", Kind = Kinds[2], Owner = Owners[2]}
};
DataContext = this;
}
private void AddOwner(object sender, RoutedEventArgs e)
{
Owners.Add(new Owner(){Name = "New Owner"});
}
}
데이터 모델 :
,489,332 10 개
PropertyChangedBase 클래스 :
public class PropertyChangedBase:INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
결과 :
이 예제에 대해 고려할 필요가 3 개 중요한 측면이 있습니다
- 내가에서 오전은 UI를 조작하는 방법은 없다. ents in code. 그것은 WPF에서 대부분의 시간을 완전히 불필요합니다.
- WPF에서 양방향 바인딩을 지원하기 위해 데이터 모델의 클래스는
INotifyPropertyChanged
을 구현합니다.
- 컬렉션은 요소 (자동
ListBoxes
등을 업데이트하기 위해) 추가/컬렉션으로부터 제거되는 경우 자동 통지를 지원하기 위해 입력 ObservableCollection<T>
의이다.
내 예제의 XAML 요소에 특정 크기 또는 Margin
값이 없다는 것을 알 수 있습니다.Margin="338,10,0,0"
과 같은 것들은 일반적으로 Visual Studio 디자이너에서 가져온 것으로, 제대로 구조화되지 않은 레이아웃을 나타냅니다. WPF (DockPanel
, StackPanel
, Grid
, UniformGrid
, WrapPanel
등)의 Layout 요소를 살펴보고 디자이너를 사용하는 대신 XAML을 직접 코딩하는 것이 좋습니다. 이렇게하면 훨씬 높은 수준의 확장 성이 가능하며 고정 위치 요소의 뉘앙스를 줄일 수 있습니다.
3 개의 텍스트 상자를 사용하지 말고 1을 사용하고 형식이 지정된 문자열로 텍스트 블록의 텍스트를 변경하거나 변환기를 사용하십시오. – David