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 并完成。
我制作了这个最小的、完整的和可验证的例子来说明我面临的挑战。它可以工作,但绝对不是 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 并完成。