StatusBar Bind to 属性 in UserControl in active tab of TabControl

StatusBar Bind to property in UserControl in active tab of TabControl

我制作了这个最小的、完整的和可验证的例子来说明我面临的挑战。它可以工作,但绝对不是 MVVM,只不过是一个 hack。

它根据用户控件中的某些 属性 更改更新状态栏。当用户更改选项卡时,它也会更新。对于真正的交易,它将显示记录计数(每个选项卡中显示多少数据行)。

必须有更简洁的方法来执行此操作...

如何使用 MVVM 完成此操作?

注意:在我的实际实现中,每个用户控件的数据上下文是不同的。因此,如果有人对涉及类似数据上下文的绑定有建议,请考虑。

主要WindowXAML

<Window x:Class="TabControlStatusBarBinding.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:TabControlStatusBarBinding"
        Title="MainWindow" Height="150" Width="300"
        x:Name="Window">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="auto"/>
        </Grid.RowDefinitions>
        <TabControl Grid.Row="0">
            <TabItem Header="Tab1">
                <local:UserControl1 x:Name="UC1_A"/>
            </TabItem>
            <TabItem Header="Tab2">
                <local:UserControl1 x:Name="UC1_B" />
            </TabItem>
            <TabItem Header="Tab3">
                <local:UserControl1 x:Name="UC1_C"/>
            </TabItem>
        </TabControl>
        <StatusBar Grid.Row="1">
            <TextBlock Text="{Binding DP_StatusBarText, ElementName=Window, FallbackValue='No Updates'}"/>
        </StatusBar>
    </Grid>
</Window>

用户控制XAML

<UserControl x:Name="MyUserControl" x:Class="TabControlStatusBarBinding.UserControl1"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" d:DesignHeight="50" d:DesignWidth="90" GotFocus="MyUserControl_GotFocus">
    <Grid Background="Gray">
        <TextBox x:Name="UC1" Text="test" HorizontalAlignment="Center" VerticalAlignment="Center" TextChanged="UC1_TextChanged"/>
    </Grid>
</UserControl>

主要Window代码隐藏

namespace TabControlStatusBarBinding
{
    public partial class MainWindow : Window
    {
        public static DependencyProperty dp_StatusBarText = DependencyProperty.Register("DP_StatusBarText", typeof(string), typeof(MainWindow));
        public string DP_StatusBarText
        {
            get { return (string)GetValue(dp_StatusBarText); }
            set { SetValue(dp_StatusBarText, value); }
        }
        public MainWindow()
        {
            InitializeComponent();

            DP_StatusBarText = "Main window loaded";

            UC1_A.StatusUpdated += MyEventHandlerFunction_StatusUpdated;
            UC1_B.StatusUpdated += MyEventHandlerFunction_StatusUpdated;
            UC1_C.StatusUpdated += MyEventHandlerFunction_StatusUpdated;
        }
        public void MyEventHandlerFunction_StatusUpdated(object sender, EventArgs e)
        {
            DP_StatusBarText = (string)sender;
        }
    }
}

背后的用户控制代码

namespace TabControlStatusBarBinding
{
    public partial class UserControl1 : UserControl
    {
        public event EventHandler StatusUpdated;
    
        public UserControl1()
        {
            InitializeComponent();
        }

        private void RaiseStatusUpdatedEvent(string SendText)
        {
            if (this.StatusUpdated != null)
                this.StatusUpdated(SendText, new EventArgs());
        }

        private void UC1_TextChanged(object sender, TextChangedEventArgs e)
        {
            RaiseStatusUpdatedEvent(UC1.Text);
        }

        private void MyUserControl_GotFocus(object sender, RoutedEventArgs e)
        {
            RaiseStatusUpdatedEvent(UC1.Text);
        }
    }
}

好吧,你的例子只使用视图 - 没有模型,没有视图模型,所以不是很清楚 MVVM 有什么问题 :) 但我会尽力帮助你介绍一些您示例中的数据。

首先,只是简单的数据项。

public class TestDataItem : INotifyPropertyChanged {
    public int ID { get; set; }
    private string _text;
    public string Text
    {
        get { return _text; }
        set
        {
            if (value == _text) return;
            _text = value;
            OnPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

用户控件 1。只需将文本框文本绑定到模型文本 属性。代码隐藏是空的。

<UserControl x:Class="WpfApplication2.UserControl1"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"              
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">
    <Grid Background="Gray">
        <TextBox Text="{Binding Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Center" VerticalAlignment="Center" />
    </Grid>
</UserControl>

Window。选项卡控件中的选项卡现在绑定到数据项列表。选项卡内容只是 UserControl1(它将继承数据上下文)。

<Window x:Class="WpfApplication2.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"                
    xmlns:wpfApplication2="clr-namespace:WpfApplication2"
    mc:Ignorable="d"
    Title="MainWindow" Height="500" Width="500">
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
        <RowDefinition Height="auto"/>
    </Grid.RowDefinitions>
    <TabControl x:Name="tabControl" Grid.Row="0" ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem}">
        <TabControl.ItemTemplate>
            <DataTemplate DataType="wpfApplication2:TestDataItem">
                <TextBlock Text="{Binding ID}" />
            </DataTemplate>
        </TabControl.ItemTemplate>
        <TabControl.ContentTemplate>
            <DataTemplate DataType="wpfApplication2:TestDataItem">
                <wpfApplication2:UserControl1 />
            </DataTemplate>
        </TabControl.ContentTemplate>
    </TabControl>
    <StatusBar Grid.Row="1">
        <TextBlock Text="{Binding SelectedItem.Text, FallbackValue='No Updates'}"/>
    </StatusBar>
</Grid>
</Window>

Window 代码隐藏:

public partial class MainWindow : Window {
    public MainWindow() {
        InitializeComponent();
        this.DataContext = new MainViewModel();
    }
}

查看模型:

 public class MainViewModel : INotifyPropertyChanged {
    public IEnumerable<TestDataItem> Items => new[] {
            new TestDataItem() {ID = 100, Text = "item1"},
            new TestDataItem() {ID = 200, Text = "item2"},
            new TestDataItem() {ID = 300, Text = "item3"}
        };

    private string _statusText = "No data selected";
    public string StatusText
    {
        get { return _statusText; }
        set
        {
            if (value == _statusText) return;
            _statusText = value;
            OnPropertyChanged();
        }
    }

    private TestDataItem _selectedItem;
    public TestDataItem SelectedItem
    {
        get { return _selectedItem; }
        set
        {
            if (Equals(value, _selectedItem)) return;
            _selectedItem = value;
            OnPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

所以我们只需将状态绑定到 SelectedItem.Text 并完成。