我是MVVM和wpf的新手......
总结形式的问题 - 如何使用wpf和MVVM控制控件的可见性。它也应该零代码。
实际场景 - 我有多个用户控制面板...说UCPanel1,UCPanel2,UCPnale3 ...直到6 - 我在一个主用户控件中导入这些用户控件...说UCMain 它有堆叠面板,顶部有按钮......就像菜单一样。 - 现在要求非常简单......在按钮1点击 - 我应该能够看到UCPanel1和剩余的面板隐藏,Button2点击 - 我应该能够看到UCPanel2和剩余的面板隐藏......等等 - 这成功地使用了背后的代码。但要求是实现这样一种方式,即在代码背后应尽可能少的代码。 那我的XAML和视图模型怎么样? 我无法在viewmodel中访问UCPanel1的扩展对象..
在MainPanel XAML中......
<Button
Style="{StaticResource StackPanelButtonStyle}"
Command="{Binding openMessageCommand}" >
<!--Click="BtnMessege_OnClick" >-->
<TextBlock
Text="Messaging"
Style="{StaticResource StackPanelButtonTextStyle}">
</TextBlock>
</Button>
<Button
Style="{StaticResource StackPanelButtonStyle}"
Command="{Binding openProductsCommand}">
<!--Click="BtnProducts_OnClick">-->
<TextBlock
Text="Products"
Style="{StaticResource StackPanelButtonTextStyle}" ></TextBlock>
</Button>
<local:StackPanelMessaging
Grid.Row="2"
Visibility="{Binding Panel1Visiblity}"></local:StackPanelMessaging>
<local:WrapPanelProducts
Grid.Row="2"
Visibility="{Binding Panel2Visiblity}" ></local:WrapPanelProducts>
在主视图模型中......
private Visibility _panel1Visiblity= Visibility.Visible;
private Visibility _panel2Visiblity= Visibility.Hidden;
public Visibility Panel1Visiblity
{
get { return _panel1Visiblity; }
set
{
if (_panel1Visiblity != value)
{
_panel1Visiblity = value;
OnPropertyChanged("Panel1Visiblity");
}
}
}
public Visibility Panel2Visiblity
{
get { return _panel2Visiblity; }
set
{
if (_panel2Visiblity != value)
{
_panel2Visiblity = value;
OnPropertyChanged("Panel2Visiblity");
}
}
}
private void OpenStackMessagePanel()
{
Panel1Visiblity = Visibility.Visible;
Panel2Visiblity = Visibility.Hidden;
}
private bool canExecuteMethod1()
{
return true;
}
private void OpenWrapProductsPanel()
{
Panel2Visiblity = Visibility.Visible;
Panel1Visiblity = Visibility.Hidden;
}
private bool canExecuteMethod2()
{
return true;
}
public ICommand openMessageCommand
{
get
{
if (_openMessageCommand == null)
{
_openMessageCommand = new DelegateCommand(OpenStackMessagePanel, canExecuteMethod1, true);
}
return _openMessageCommand;
}
}
public ICommand openProductsCommand
{
get
{
if (_openProductsCommand == null)
{
_openProductsCommand = new DelegateCommand(OpenWrapProductsPanel, canExecuteMethod2, true);
}
return _openProductsCommand;
}
}
另外,我觉得写这么多代码真的值得吗?或者我应该优先选择仅仅10行的代码......
答案 0 :(得分:0)
通过使用命令和可见性,您可以实现您想要的效果。这是一个简单的例子。我没有像你一样使用用户控件,但是通过这个例子,你应该明白这个想法。只需用您的用户控件替换网格即可。
我要做的第一件事是创建一个BooleanToVisibilityConverter类。这是一个将布尔值转换为可见性的转换器。我们不希望将Visibility属性放在ViewModel中,因为我们希望将UI与逻辑分开。所以我们在ViewModel中想要的是一个简单的布尔值,它将告诉面板是否可见。
public class BooleanToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
bool? boolValue = value as bool?;
return boolValue.HasValue && boolValue.Value ? Visibility.Visible : Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
Visibility? visibilityValue = value as Visibility?;
return visibilityValue.HasValue && visibilityValue.Value == Visibility.Visible;
}
}
Now in your MainViewModel class, you will have six boolean properties that will tell if your panel is visible or not. And then you will have 6 command properties that will set those boolean properties to true.
public class MainViewModel : BindableBase
{
private bool _IsPanel1Visible;
public bool IsPanel1Visible
{
get { return _IsPanel1Visible; }
set { SetProperty(ref _IsPanel1Visible, value); }
}
private bool _IsPanel2Visible;
public bool IsPanel2Visible
{
get { return _IsPanel2Visible; }
set { SetProperty(ref _IsPanel2Visible, value); }
}
private bool _IsPanel3Visible;
public bool IsPanel3Visible
{
get { return _IsPanel3Visible; }
set { SetProperty(ref _IsPanel3Visible, value); }
}
private bool _IsPanel4Visible;
public bool IsPanel4Visible
{
get { return _IsPanel4Visible; }
set { SetProperty(ref _IsPanel4Visible, value); }
}
private bool _IsPanel5Visible;
public bool IsPanel5Visible
{
get { return _IsPanel5Visible; }
set { SetProperty(ref _IsPanel5Visible, value); }
}
private bool _IsPanel6Visible;
public bool IsPanel6Visible
{
get { return _IsPanel6Visible; }
set { SetProperty(ref _IsPanel6Visible, value); }
}
public ICommand ShowPanel1Command { get { return new DelegateCommand(() => { HidePanels(); IsPanel1Visible = true; }); } }
public ICommand ShowPanel2Command { get { return new DelegateCommand(() => { HidePanels(); IsPanel2Visible = true; }); } }
public ICommand ShowPanel3Command { get { return new DelegateCommand(() => { HidePanels(); IsPanel3Visible = true; }); } }
public ICommand ShowPanel4Command { get { return new DelegateCommand(() => { HidePanels(); IsPanel4Visible = true; }); } }
public ICommand ShowPanel5Command { get { return new DelegateCommand(() => { HidePanels(); IsPanel5Visible = true; }); } }
public ICommand ShowPanel6Command { get { return new DelegateCommand(() => { HidePanels(); IsPanel6Visible = true; }); } }
private void HidePanels()
{
IsPanel1Visible = false;
IsPanel2Visible = false;
IsPanel3Visible = false;
IsPanel4Visible = false;
IsPanel5Visible = false;
IsPanel6Visible = false;
}
}
现在在你的xaml中,你只需要将布尔属性绑定到面板的可见性,并使用BooleanToVisibilityConverter将布尔值转换为可见性。您还需要将按钮绑定到命令。
<Grid>
<Grid.DataContext>
<local:MainViewModel />
</Grid.DataContext>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.Resources>
<local:BooleanToVisibilityConverter x:Key="booleanToVisibilityConverter" />
</Grid.Resources>
<StackPanel Orientation="Horizontal">
<Button Content="Show Panel 1" Command="{Binding ShowPanel1Command}" />
<Button Content="Show Panel 2" Command="{Binding ShowPanel2Command}" />
<Button Content="Show Panel 3" Command="{Binding ShowPanel3Command}" />
<Button Content="Show Panel 4" Command="{Binding ShowPanel4Command}" />
<Button Content="Show Panel 5" Command="{Binding ShowPanel5Command}" />
<Button Content="Show Panel 6" Command="{Binding ShowPanel6Command}" />
</StackPanel>
<StackPanel Grid.Row="1">
<Grid Visibility="{Binding IsPanel1Visible, UpdateSourcetrigger PropertyChanged, Converter={StaticResource booleanToVisibilityConverter}}">
<TextBlock Text="Panel 1" />
</Grid>
<Grid Visibility="{Binding IsPanel2Visible, UpdateSourcetrigger PropertyChanged, Converter={StaticResource booleanToVisibilityConverter}}">
<TextBlock Text="Panel 2" />
</Grid>
<Grid Visibility="{Binding IsPanel3Visible, UpdateSourcetrigger PropertyChanged, Converter={StaticResource booleanToVisibilityConverter}}">
<TextBlock Text="Panel 3" />
</Grid>
<Grid Visibility="{Binding IsPanel4Visible, UpdateSourcetrigger PropertyChanged, Converter={StaticResource booleanToVisibilityConverter}}">
<TextBlock Text="Panel 4" />
</Grid>
<Grid Visibility="{Binding IsPanel5Visible, UpdateSourcetrigger PropertyChanged, Converter={StaticResource booleanToVisibilityConverter}}">
<TextBlock Text="Panel 5" />
</Grid>
<Grid Visibility="{Binding IsPanel6Visible, UpdateSourcetrigger PropertyChanged, Converter={StaticResource booleanToVisibilityConverter}}">
<TextBlock Text="Panel 6" />
</Grid>
</StackPanel>
</Grid>
已更新: 在显示另一个面板之前隐藏所有面板。
答案 1 :(得分:0)
<!--Button1-->
<Button Style="{StaticResource StackPanelButtonStyle}" Command="{Binding openPanelCommd}" CommandParameter="{Binding ElementName=WrapPanel1}" >
<TextBlock Text="1" Style="{StaticResource StackPanelButtonTextStyle}">
</TextBlock>
</Button>
<!--Button2-->
<Button Style="{StaticResource StackPanelButtonStyle}" Command="{Binding openPanelCommd}" CommandParameter="{Binding ElementName=WrapPanel2}" >
<TextBlock Text="2" Style="{StaticResource StackPanelButtonTextStyle}"></TextBlock>
</Button>
<!--Button3-->
<Button Style="{StaticResource StackPanelButtonStyle}" Command="{Binding openPanelCommd}" CommandParameter="{Binding ElementName=WrapPanel3}" >
<TextBlock Text="3" Style="{StaticResource StackPanelButtonTextStyle}" ></TextBlock>
</Button>
<!--Button4-->
<Button Style="{StaticResource StackPanelButtonStyle}" Command="{Binding openPanelCommd}" CommandParameter="{Binding ElementName=WrapPanel4}" >
<TextBlock Text="4" Style="{StaticResource StackPanelButtonTextStyle}" ></TextBlock>
</Button>
<!--Button5-->
<Button Style="{StaticResource StackPanelButtonStyle}" Command="{Binding openPanelCommd}" CommandParameter="{Binding ElementName=WrapPanel5}" >
<TextBlock Text="5" Style="{StaticResource StackPanelButtonTextStyle}"></TextBlock>
</Button>
<!--Panels-->
<local:WrapPanelProducts x:Name="WrapPanel1" Grid.Row="2"
Visibility="Collapsed"/>
<local:WrapPanelProducts x:Name="WrapPanel2" Grid.Row="2"
Visibility="Collapsed"/>
<local:WrapPanelProducts x:Name="WrapPanel3" Grid.Row="2"
Visibility="Collapsed"/>
<local:WrapPanelProducts x:Name="WrapPanel4" Grid.Row="2"
Visibility="Collapsed"/>
<local:WrapPanelProducts x:Name="WrapPanel5" Grid.Row="2"
Visibility="Collapsed"/>
Code Behind是
public StackPanelMain()
{
InitializeComponent();
StackPanelMainViewModel StackPanelMainViewModel1 = new StackPanelMainViewModel();
this.DataContext = StackPanelMainViewModel1;
}
和View型号代码如下......
public RelayCommand openPanelCommd { get; set; }
//Constructor
public StackPanelMainViewModel()
{
openPanelCommd = new RelayCommand(OpenPanel);
}
private void OpenPanel(object parameter)
{
var args = (object) parameter;
var elementname = (UIElement) args;
elementname.Visibility = Visibility.Visible;
}