簡體   English   中英

WPF中的數據綁定

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM