我是C#编程新手,希望对我的问题有一些见解。
我有一个标准视图,其中包含一个导航菜单,通过点击导航按钮,它将在标准视图中显示另一个视图。我的问题是,我需要将导航按钮与视图中的一些按钮 "同步",以便当其中一个按钮被关注时,两个按钮都被关注。
我正在使用MVVM与caliburn.micro,但我不知道如何从视图中的viewmodels中访问控件,就像你可以从后面的代码中访问一样......我想我需要用一个布尔值来设置聚焦属性,使两个按钮都被链接起来,但我不知道如何做。
使用MVVM,你不想从viewModels中访问控件,因为这将违背MVVM试图从视图中解耦viewmodels的观点.如果你要使用访问viewmodel中的控件,那么你将无法在不改变viewmodel的情况下改变视图。
当你想从你的视图中传输信息到你的viewModel时,你可以使用Binding.这里的一种可能性是在你的viewModel中拥有焦点的视图信息,并让视图对变化做出反应。
在你的viewModel中,
public class MainWindowViewModel : INotifyPropertyChanged
{
/// <summary>
/// The list of views (the enum doesn't have to be in the viewModel, it can be anywhere)
/// </summary>
public enum Views
{
View1,
View2,
View3
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyChange(PropertyChangedEventArgs e)
{
PropertyChanged?.Invoke(this, e);
}
private Views focusedView;
/// <summary>
/// View with the focus
/// </summary>
public Views FocusedView
{
get
{
return this.focusedView;
}
set
{
this.focusedView = value;
NotifyChange(new PropertyChangedEventArgs("FocusedView"));
}
}
/// <summary>
/// Constructor
/// </summary>
public MainWindowViewModel()
{
this.FocusedView = Views.View1;
}
}
MainWindow.xaml:
<Window.Resources>
<local:MultiValueEqualityConverter x:Key="MultiValueEqualityConverter" />
<Style x:Key="focusedButtonStyle" TargetType="{x:Type Button}">
<Setter Property="BorderBrush" Value="Gray"/>
<Style.Triggers>
<DataTrigger Value="True">
<DataTrigger.Binding>
<!--It is not possible to make a datatrigger with a Binding in the value Property
so the MultiBinding is a neat trick to avoid having to adapt the style for each Button-->
<MultiBinding Converter="{StaticResource MultiValueEqualityConverter}">
<Binding RelativeSource="{RelativeSource Self}"
Path="Tag" Mode="OneWay"/>
<Binding RelativeSource="{RelativeSource Self}"
Path="DataContext.FocusedView" Mode="OneWay"
UpdateSourceTrigger="PropertyChanged" />
</MultiBinding>
</DataTrigger.Binding>
<Setter Property="BorderBrush" Value="Red" />
<Setter Property="BorderThickness" Value="2" />
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<StackPanel Orientation="Vertical" Grid.Column="0">
<Button Margin="5" Content="View1" GotFocus="Button_GotFocus"
Tag="{x:Static local:MainWindowViewModel+Views.View1}"
Style="{StaticResource focusedButtonStyle}">
</Button>
<Button Margin="5" Content="View2" GotFocus="Button_GotFocus"
Tag="{x:Static local:MainWindowViewModel+Views.View2}"
Style="{StaticResource focusedButtonStyle}" />
<Button Margin="5" Content="View3" GotFocus="Button_GotFocus"
Tag="{x:Static local:MainWindowViewModel+Views.View3}"
Style="{StaticResource focusedButtonStyle}" />
</StackPanel>
<StackPanel Orientation="Horizontal" Grid.Column="1" MaxHeight="30" VerticalAlignment="Top" >
<Button Margin="5" Content="View1" GotFocus="Button_GotFocus"
Tag="{x:Static local:MainWindowViewModel+Views.View1}"
Style="{StaticResource focusedButtonStyle}" />
<Button Margin="5" Content="View2" GotFocus="Button_GotFocus"
Tag="{x:Static local:MainWindowViewModel+Views.View2}" Style="{StaticResource focusedButtonStyle}"/>
<Button Margin="5" Content="View3" GotFocus="Button_GotFocus"
Tag="{x:Static local:MainWindowViewModel+Views.View3}" Style="{StaticResource focusedButtonStyle}" />
</StackPanel>
</Grid>
MainWindow.xaml.cs:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new MainWindowViewModel();
}
private void Button_GotFocus(object sender, RoutedEventArgs e)
{
if( sender is Button button && this.DataContext is MainWindowViewModel vm)
{
//The information is stored in the tag in order to avoid aving to do as switch or if statement
vm.FocusedView = (MainWindowViewModel.Views)button.Tag;
}
}
}
多重绑定(源码:https:/stackover) https:/stackoverflow.coma5144263413448212。 )
public class MultiValueEqualityConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
return values?.All(o => o?.Equals(values[0]) == true) == true || values?.All(o => o == null) == true;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
你会注意到我并没有改变按钮的 "IsFocused "属性,实际上你可以使用Property="FocusManager.FocusedElement "来设置它,但我相信你必须使用元素的名称来设置焦点,所以你必须调整每个按钮的样式,通过名称来引用其他按钮。
让我知道这对你来说是否可以,这是我的第一篇文章,所以我可能已经忘记了一些事情。