WPF中的数据绑定

时间:2016-10-30 19:39:30

标签: wpf

“EDIT”

  

我想要达到的目标是 -

     

MainWindow.xaml包含一个Button,一个ComboBox和一个ContentControl。   UserControl-A和UserControl-C都包含ContentControl。   UserControl-B和UserControl-D都包含TextBlock。

     

UserControl-B将包含在ContentControl的内容中   用户控件-A。 UserControl-D将是ContentControl的内容   包含在UserControl-C中。

     

UserControl-A或UserControl-C将是ContentControl的内容   单击Button时包含在MainWindow.xaml中。

     

更改Combobox更新TextBlock的SelectedValue   UserControl-B或UserControl-D。

“EDIT”

除了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类的静态属性的情况下实现相同的功能?

1 个答案:

答案 0 :(得分:0)

我从ComboItems.cs中删除了“ComboItems and 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}" />

完成!