[英]Databind in WPF
“編輯”
我想要實現的是-
MainWindow.xaml包含一個Button,一個ComboBox和一個ContentControl。 UserControl-A和UserControl-C都包含一個ContentControl。 UserControl-B和UserControl-D都包含一個TextBlock。
UserControl-B將是UserControl-A中包含的ContentControl的內容。 UserControl-D將是UserControl-C中包含的ContentControl的內容。
單擊“按鈕”,UserControl-A或UserControl-C將成為MainWindow.xaml中包含的ContentControl的內容。
在Combobox的SelectedValue更改時,更新UserControl-B或UserControl-D的TextBlock。
“編輯”
除了MainWindow.xaml,App.xaml和App.config,我在我的項目中還有MainContent1.xaml,MainContent2.xaml,ComboItems.cs和兩個子文件夾Sub1和Sub2,它們每個都包含一個名為S1.xaml的文件。
我所有的代碼都在ComboItems.cs中寫為-
namespace MultiBinding
{
public class Item
{
public string Name { get; set; }
public int Id { get; set; }
}
public class ComboItems
{
public ComboItems()
{
Items = new List<Item>(3);
for (int i = 1; i < 4; i++)
Items.Add(new Item { Id = i, Name = "Name " + i });
}
public List<Item> Items { get; set; }
}
public class ButtonContent : INotifyPropertyChanged
{
public ICommand MyCommand { get; set; }
private string _content;
public ButtonContent()
{
_content = "First";
MyCommand = new Command(Do, CanDo);
}
public string Content
{
get { return _content; }
set { _content = value; OnChange("Content"); }
}
private bool CanDo(object parameter) => true;
private void Do(object parameter) => Content = Content == "First" ? "Second" : "First";
public event PropertyChangedEventHandler PropertyChanged;
private void OnChange(string name) =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
public class Command : ICommand
{
private Action<object> Do;
private Func<object, bool> CanDo;
public Command(Action<object> Do, Func<object, bool> CanDo)
{
this.Do = Do;
this.CanDo = CanDo;
}
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter) => true;
public void Execute(object parameter) => Do(parameter);
}
public class SomeText
{
public static string Text1 { get; set; }
public static string Text2 { get; set; }
}
public class Converter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
switch (values[1].ToString())
{
case "1": SomeText.Text1 = SomeText.Text2 = "Selected Item is 1"; break;
case "2": SomeText.Text1 = SomeText.Text2 = "Selected Item is 2"; break;
case "3": SomeText.Text1 = SomeText.Text2 = "Selected Item is 3"; break;
}
if (values[0].ToString() == "First") return new MainContent1();
else return new MainContent2();
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
MainWindow.xaml的內容是-
<Window x:Class="MultiBinding.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MultiBinding">
<Window.Resources>
<local:ComboItems x:Key="cboItems" />
<local:Item x:Key="Item" />
<local:Converter x:Key="convert" />
<local:ButtonContent x:Key="content"/>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="10*"/>
<RowDefinition Height="90*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<ComboBox x:Name="combo"
DataContext="{Binding Source={StaticResource Item}}"
ItemsSource="{Binding Path=Items, Source={StaticResource cboItems}}"
DisplayMemberPath="Name"
SelectedValuePath="Id"
SelectedValue="{Binding Path=Id}"/>
<Button x:Name="butt" Grid.Column="1"
DataContext="{Binding Source={StaticResource content}}"
Content="{Binding Path=Content}"
Command="{Binding Path=MyCommand}"/>
<ContentControl Grid.Row="1" Grid.ColumnSpan="2">
<ContentControl.Content>
<MultiBinding Converter="{StaticResource convert}">
<Binding ElementName="butt" Path="Content"/>
<Binding ElementName="combo" Path="SelectedValue"/>
</MultiBinding>
</ContentControl.Content>
</ContentControl>
</Grid>
MainContent1.xaml的內容是-
<UserControl x:Class="MultiBinding.MainContent1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sub="clr-namespace:MultiBinding.Sub1">
<UserControl.Resources>
<sub:S1 x:Key="s1"/>
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock FontSize="20" Text="On Main ContentControl No. 1"/>
<ContentControl
Content="{Binding Source={StaticResource s1}}"
Grid.Row="1"/>
</Grid>
MainContent2.xaml包含與上面完全相同的代碼,除了
xmlns:sub="clr-namespace:MultiBinding.Sub2"
文件夾Sub1下的S1.xaml的內容是-
<UserControl x:Class="MultiBinding.Sub1.S1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:main="clr-namespace:MultiBinding">
<UserControl.Resources>
<main:SomeText x:Key="MyText"/>
</UserControl.Resources>
<Grid Background="Bisque">
<TextBlock Text="{Binding Text1, Source={StaticResource MyText}}" />
</Grid>
Sub2文件夾下的S1.xaml與Sub1文件夾的相似
<TextBlock Text="{Binding Path=Text2, Source={StaticResource MyText}}" />
一切都按這種方式工作。
在ComboItems.cs中使用SomeText類的Text1和Text2屬性的靜態關鍵字infront是否有任何問題?
如何在不使用SomeText類的靜態屬性的情況下實現相同的功能?
我從ComboItems.cs中刪除了“ ComboItems和Converter”類,將“ ButtonContent”類重命名為“ MyCode”,並如下實現了它-
public class MyCode : INotifyPropertyChanged
{
//Fields
private Sub1.S1 _s1;
private Sub2.S1 _s2;
private MainContent1 _m1;
private MainContent2 _m2;
private object _mainContent;
private object _subContent;
private int _selectedIndex;
//Properties
public string Text { get; set; }
public List<Item> Items { get; set; }
public ICommand MyCommand { get; set; }
public string Content { get; set; }
public object MainContent
{
get { return _mainContent; }
set { _mainContent = value; OnChange("MainContent"); }
}
public object SubContent
{
get { return _subContent; }
set { _subContent = value; OnChange("SubContent"); }
}
public int SelectedIndex
{
get { return _selectedIndex; }
set
{
_selectedIndex = value;
//Action on selection change
switch (_selectedIndex)
{
case 0: Text = "Selected Item is 1"; break;
case 1: Text = "Selected Item is 2"; break;
case 2: Text = "Selected Item is 3"; break;
}
OnChange("Text");
}
}
//Constructor
public MyCode()
{
Content = "First";
MyCommand = new Command(Do, CanDo);
_m1 = new MainContent1();
_m2 = new MainContent2();
_s1 = new Sub1.S1();
_s2 = new Sub2.S1();
MainContent = _m1;
SubContent = _s1;
Items = new List<Item>(3);
for (int i = 1; i < 4; i++)
Items.Add(new Item { Id = i, Name = "Name " + i });
SelectedIndex = 0;
}
//Action on Button Click
private void Do(object parameter)
{
if(Content == "First")
{
MainContent = _m2;
SubContent = _s2;
Content = "Second";
}
else
{
MainContent = _m1;
SubContent = _s1;
Content = "First";
}
OnChange("Content");
}
private bool CanDo(object parameter) => true;
//Inotify
public event PropertyChangedEventHandler PropertyChanged;
private void OnChange(string name) =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
將MainWindow.xaml更改為-
<Window.Resources>
<local:MyCode x:Key="Code"/>
</Window.Resources>
<Grid DataContext="{Binding Source={StaticResource Code}}">
<Grid.RowDefinitions...>
<Grid.ColumnDefinitions...>
<ComboBox ItemsSource="{Binding Path=Items}"
DisplayMemberPath="Name"
SelectedValuePath="Id"
SelectedIndex="{Binding Path=SelectedIndex}"/>
<Button x:Name="butt" Grid.Column="1"
Content="{Binding Path=Content}"
Command="{Binding Path=MyCommand}"/>
<ContentControl Grid.Row="1" Grid.ColumnSpan="2"
Content="{Binding Path=MainContent}"/>
</Grid>
MainContent1.xaml和MainContent2.xaml現在都包含-
<ContentControl Content="{Binding Path=SubContent}"/>
文件夾Sub1和Sub2下的S1.xaml包含-
<TextBlock Text="{Binding Path=Text}" />
做完了!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.