Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Datová vazba v aplikacích WinUI umožňuje efektivně připojit ovládací prvky ke zdrojům dat. Zjistěte, jak svázat ovládací prvek s jednou položkou nebo kolekcí položek, jak řídit vykreslování položek, implementovat detailní zobrazení a formátovat data pro zobrazení. Další podrobnosti najdete v tématu Hloubková datová vazba.
Požadavky
V tomto tématu se předpokládá, že víte, jak vytvořit základní aplikaci WinUI pomocí sady Windows App SDK. Pokyny k vytvoření první aplikace WinUI najdete v tématu Vytvoření aplikace WinUI.
Vytvoření projektu
Vytvořte novou prázdnou aplikaci WinUI, zabalený projekt C#. Pojmenujte ho "Rychlý start".
Navázat na jednu položku
Každá vazba se skládá z cíle vazby a zdroje vazby. Cíl je obvykle vlastnost ovládacího prvku nebo jiného prvku uživatelského rozhraní a zdrojem je vlastnost instance třídy (datový model nebo model zobrazení). Tento příklad ukazuje, jak vytvořit vazbu ovládacího prvku na jednu položku. Cílem je vlastnost Text objektu TextBlock. Zdrojem je instance jednoduché třídy s názvem Recording, která představuje záznam zvuku. Podívejme se nejprve na třídu.
Přidejte do projektu novou třídu a pojmenujte ji Recording.
namespace Quickstart
{
public class Recording
{
public string ArtistName { get; set; }
public string CompositionName { get; set; }
public DateTime ReleaseDateTime { get; set; }
public Recording()
{
ArtistName = "Wolfgang Amadeus Mozart";
CompositionName = "Andante in C for Piano";
ReleaseDateTime = new DateTime(1761, 1, 1);
}
public string OneLineSummary
{
get
{
return $"{CompositionName} by {ArtistName}, released: "
+ ReleaseDateTime.ToString("d");
}
}
}
public class RecordingViewModel
{
private Recording defaultRecording = new();
public Recording DefaultRecording { get { return defaultRecording; } }
}
}
Dále zpřístupněte zdroj vazby z třídy, která reprezentuje vaše okno značkování. Přidejte vlastnost typu RecordingViewModel do MainWindow.xaml.cs.
namespace Quickstart
{
public sealed partial class MainWindow : Window
{
public MainWindow()
{
this.InitializeComponent();
}
public RecordingViewModel ViewModel{ get; } = new RecordingViewModel();
}
}
Poslední krok je svázání TextBlock s vlastností ViewModel.DefaultRecording.OneLineSummary.
<Window x:Class="Quickstart.MainWindow" ... >
<Grid>
<TextBlock Text="{x:Bind ViewModel.DefaultRecording.OneLineSummary}"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Grid>
</Window>
Tady je výsledek.
Vytvoření vazby k kolekci položek
Běžným scénářem je vytvoření vazby na kolekci obchodních objektů. V jazyce C# použijte obecnou třídu ObservableCollection<T> pro datovou vazbu. Implementuje INotifyCollectionChanged rozhraní, které poskytuje oznámení o změně vazby při přidání nebo odebrání položek. Kvůli známé chybě v režimu vydání WinUI s .NET 8 a novějším ale může být potřeba použít seznam<T> v některých scénářích, zejména pokud je vaše kolekce statická a po inicializaci se nezmění. Pokud vaše uživatelské rozhraní potřebuje aktualizovat, když se kolekce změní za běhu, použijte ObservableCollection<T>. Pokud potřebujete zobrazit jenom pevnou sadu položek, List<T> stačí. Pokud chcete, aby se vázané ovládací prvky aktualizovaly o změny vlastností objektů v kolekci, měly by tyto objekty implementovat INotifyPropertyChanged. Další informace naleznete v tématu , Datové vazby podrobně,.
Poznámka
Používáním List<T>se nemusí zobrazovat oznámení o změnách kolekce. Pokud potřebujete reagovat na změny, zvažte použití ObservableCollection<T>. V tomto příkladu nemusíte reagovat na změny kolekce, takže List<T> stačí.
Následující příklad vytvoří vazbu ListView na kolekci Recording objektů. Nejprve přidejte kolekci do modelu zobrazení. Přidejte tyto nové členy do RecordingViewModel třídy.
public class RecordingViewModel
{
...
private List<Recording> recordings = new();
public List<Recording> Recordings{ get{ return recordings; } }
public RecordingViewModel()
{
recordings.Add(new Recording(){ ArtistName = "Johann Sebastian Bach",
CompositionName = "Mass in B minor", ReleaseDateTime = new DateTime(1748, 7, 8) });
recordings.Add(new Recording(){ ArtistName = "Ludwig van Beethoven",
CompositionName = "Third Symphony", ReleaseDateTime = new DateTime(1805, 2, 11) });
recordings.Add(new Recording(){ ArtistName = "George Frideric Handel",
CompositionName = "Serse", ReleaseDateTime = new DateTime(1737, 12, 3) });
}
}
Pak vytvořte vazbu ListView na ViewModel.Recordings vlastnost.
<Window x:Class="Quickstart.MainWindow" ... >
<Grid>
<ListView ItemsSource="{x:Bind ViewModel.Recordings}"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Grid>
</Window>
Ještě nemáte k dispozici šablonu dat pro Recording třídu, takže nejlepší, co může architektura uživatelského rozhraní udělat, je volat ToString pro každou položku v ListView. Výchozí implementace ToString vrátí název typu.
Chcete-li tento problém vyřešit, můžete buď přepsat ToString, aby vracelo hodnotu OneLineSummary, nebo zadat šablonu pro data. Možnost šablony dat je běžnější a flexibilnější řešení. Šablonu dat zadáte pomocí vlastnosti ContentTemplate ovládacího prvku obsahu nebo vlastnosti ItemTemplate ovládacího prvku items. Tady jsou dva způsoby, jak navrhnout šablonu dat pro Recording společně s obrázkem výsledku.
<ListView ItemsSource="{x:Bind ViewModel.Recordings}"
HorizontalAlignment="Center" VerticalAlignment="Center">
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:Recording">
<TextBlock Text="{x:Bind OneLineSummary}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<ListView ItemsSource="{x:Bind ViewModel.Recordings}"
HorizontalAlignment="Center" VerticalAlignment="Center">
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:Recording">
<StackPanel Orientation="Horizontal" Margin="6">
<SymbolIcon Symbol="Audio" Margin="0,0,12,0"/>
<StackPanel>
<TextBlock Text="{x:Bind ArtistName}" FontWeight="Bold"/>
<TextBlock Text="{x:Bind CompositionName}"/>
</StackPanel>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Další informace o syntaxi XAML naleznete v tématu Vytvoření uživatelského rozhraní pomocí xaml. Další informace o rozložení ovládacího prvku naleznete v tématu Definovat rozložení pomocí xaml.
Přidejte zobrazení podrobností
V ListView si můžete vybrat zobrazit všechny podrobnosti o objektech Recording v položkách. Ale tento přístup zabírá hodně místa. Místo toho můžete v položce zobrazit jenom dostatek dat, abyste je identifikovali. Když uživatel provede výběr, můžete zobrazit všechny podrobnosti vybrané položky v samostatném uživatelském rozhraní, které se označuje jako zobrazení podrobností. Toto uspořádání se také označuje jako zobrazení předlohy/podrobností nebo zobrazení seznamu/podrobností.
Toto uspořádání můžete implementovat dvěma způsoby. Zobrazení podrobností lze propojit s vlastností SelectedItem v prvku ListView. Nebo můžete použít CollectionViewSource. V tomto případě svážete jak ListView, tak podrobnosti pohledu k CollectionViewSource. Tento přístup se postará o aktuálně vybranou položku za vás. Obě techniky jsou uvedené v následujících částech a oba poskytují stejné výsledky (jak je znázorněno na obrázku).
Poznámka
Zatím jste v tomto tématu použili pouze rozšíření značek {x:Bind}. Obě techniky uvedené v následujících částech však vyžadují flexibilnější (ale méně výkonné) rozšíření zápisu {Binding}.
Nejprve tady je technika SelectedItem. V případě aplikace v jazyce C# je jedinou potřebnou změnou změna markupu.
<Window x:Class="Quickstart.MainWindow" ... >
<Grid>
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<ListView x:Name="recordingsListView" ItemsSource="{x:Bind ViewModel.Recordings}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:Recording">
<StackPanel Orientation="Horizontal" Margin="6">
<SymbolIcon Symbol="Audio" Margin="0,0,12,0"/>
<StackPanel>
<TextBlock Text="{x:Bind CompositionName}"/>
</StackPanel>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<StackPanel DataContext="{Binding SelectedItem, ElementName=recordingsListView}"
Margin="0,24,0,0">
<TextBlock Text="{Binding ArtistName}"/>
<TextBlock Text="{Binding CompositionName}"/>
<TextBlock Text="{Binding ReleaseDateTime}"/>
</StackPanel>
</StackPanel>
</Grid>
</Window>
U techniky CollectionViewSource nejprve přidejte CollectionViewSource jako prostředek na nejvyšší úrovni Grid.
<Grid.Resources>
<CollectionViewSource x:Name="RecordingsCollection" Source="{x:Bind ViewModel.Recordings}"/>
</Grid.Resources>
Poznámka
Třída Window ve WinUI nemá vlastnost Resources. Místo toho můžete CollectionViewSource přidat do prvku nejvyšší úrovně Grid (nebo jiného nadřazeného prvku uživatelského rozhraní, jako je StackPanel). Pokud pracujete v rámci Page, můžete CollectionViewSource přidat do Page.Resources.
Potom upravte vazby v Objektu ListView (které již nemusí být pojmenovány) a v zobrazení podrobností použijte CollectionViewSource. Vazbou podrobností přímo na CollectionViewSource vyjadřujete záměr vázat na aktuální položku, a to ve vazbách, kde cesta nemůže být nalezena v samotné kolekci. Není nutné zadávat vlastnost CurrentItem jako cestu pro vazbu, i když to můžete udělat, pokud existuje nějaká nejednoznačnost.
...
<ListView ItemsSource="{Binding Source={StaticResource RecordingsCollection}}">
...
<StackPanel DataContext="{Binding Source={StaticResource RecordingsCollection}}" ...>
...
A tady je stejný výsledek v každém případě.
Formátování nebo převod hodnot dat pro zobrazení
Výše uvedené vykreslování má problém. Vlastnost ReleaseDateTime není jenom datum, jedná se o DateTime. Zobrazí se tedy s větší přesností, než potřebujete. Jedním z řešení je přidat řetězcovou vlastnost do třídy Recording, která vrací ekvivalent ReleaseDateTime.ToString("d"). Pojmenování této vlastnosti ReleaseDate označuje, že vrací datum, nikoli datum a čas. Pojmenování ReleaseDateAsString dále označuje, že vrací řetězec.
Flexibilnějším řešením je použít převaděč hodnot. Tady je příklad, jak vytvořit vlastní převaděč hodnot. Do souboru zdrojového kódu Recording.cs přidejte následující kód.
public class StringFormatter : Microsoft.UI.Xaml.Data.IValueConverter
{
// This converts the value object to the string to display.
// This will work with most simple types.
public object Convert(object value, Type targetType,
object parameter, string language)
{
// Retrieve the format string and use it to format the value.
string formatString = parameter as string;
if (!string.IsNullOrEmpty(formatString))
{
return string.Format(formatString, value);
}
// If the format string is null or empty, simply
// call ToString() on the value.
return value.ToString();
}
// No need to implement converting back on a one-way binding
public object ConvertBack(object value, Type targetType,
object parameter, string language)
{
throw new NotImplementedException();
}
}
Nyní můžete přidat instanci StringFormatter jako zdroj a použít ji ve vazbě TextBlock, která zobrazuje vlastnost ReleaseDateTime.
<Grid.Resources>
...
<local:StringFormatter x:Key="StringFormatterValueConverter"/>
</Grid.Resources>
...
<TextBlock Text="{Binding ReleaseDateTime,
Converter={StaticResource StringFormatterValueConverter},
ConverterParameter=Released: \{0:d\}}"/>
...
Jak můžete vidět, pro formátování flexibility, kód předává formátovací řetězec do převaděče prostřednictvím parametru převaděče. V příkladu kódu uvedeném v tomto tématu používá převaděč hodnot jazyka C#tento parametr.
Tady je výsledek.
Rozdíly mezi Binding a x:Bind
Při práci s datovými vazbami v aplikacích WinUI můžete narazit na dva primární mechanismy vazby: Binding a x:Bind. I když oba slouží k propojení prvků uživatelského rozhraní se zdroji dat, mají odlišné rozdíly:
-
x:Bind: Nabízí kontrolu času kompilace, lepší výkon a silné typování. Je ideální pro scénáře, ve kterých znáte datovou strukturu v době kompilace. -
Binding: Poskytuje vyhodnocení za běhu a je flexibilnější pro dynamické scénáře, například v případě, že datová struktura není v době kompilace známá.
Scénáře, které x:Bind nepodporuje
I když x:Bind je výkonná, nemůžete ji použít v určitých scénářích:
-
Dynamické datové struktury: Pokud datová struktura není v době kompilace známá, nemůžete použít
x:Bind. -
Vazba element-to-element:
x:Bindnepodporuje vazbu přímo mezi dvěma prvky uživatelského rozhraní. -
Vazba na
DataContext:x:Bindautomaticky nedědíDataContextod nadřazeného prvku. -
Obousměrné vazby s
Mode=TwoWay: Ačkoli jsou podporovány,x:Bindvyžaduje explicitní implementaciINotifyPropertyChangedjakékoli vlastnosti, kterou má uživatelské rozhraní aktualizovat při změně zdroje, a to jak při jednosměrné, tak obousměrné vazbě. Hlavní rozdíl u obousměrných vazeb spočívá v tom, že změny také proudí z uživatelského rozhraní zpět do zdroje.
Praktické příklady a hlubší pochopení toho, kdy je použít, najdete v následujících tématech:
Související obsah
Windows developer