【问题标题】:MultiBinding of grid visiblity in WPFWPF中网格可见性的多重绑定
【发布时间】:2018-10-13 16:28:04
【问题描述】:

我有一个列表视图项目 我想折叠列表行中的一些项目 我正在使用网格来编辑数据模板。 我尝试使用参数的多重绑定 但是我得到了“DependencyProperty.UnsetValue” 很高兴有一个代码示例。

如果我使用 1 个参数都很好。

谁能给我解释一下如何使用多重绑定 会对代码示例感到满意。 谢谢。

1 个参数的工作代码我可以使用此代码:

<ListView x:Name="LVGuiCoreBus" ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.HorizontalScrollBarVisibility="Auto" MouseDown="LVGui_MouseDown"  Grid.Row="1" >               
    <ListView.ItemTemplate>
        <DataTemplate>
            <Grid Visibility="{Binding Source, Converter={StaticResource VisiblieGroupFilterBySourcecs}}">                                                                                                                              
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="130"></ColumnDefinition>
                    <ColumnDefinition Width="10"></ColumnDefinition>
                    <ColumnDefinition Width="50"></ColumnDefinition>
                    <ColumnDefinition Width="10"></ColumnDefinition>
                    <ColumnDefinition Width="50"></ColumnDefinition>
                    <ColumnDefinition Width="10"></ColumnDefinition>
                    <ColumnDefinition Width="100"></ColumnDefinition>
                    <ColumnDefinition Width="10"></ColumnDefinition>                                                      
                    <ColumnDefinition Width="70"></ColumnDefinition>
                    <ColumnDefinition Width="10"></ColumnDefinition>
                    <ColumnDefinition Width="150"></ColumnDefinition>
                    <ColumnDefinition Width="10"></ColumnDefinition>
                    <ColumnDefinition Width="150"></ColumnDefinition>
                    <ColumnDefinition Width="10"></ColumnDefinition>
                    <ColumnDefinition Width="1*"></ColumnDefinition>
                </Grid.ColumnDefinitions>

                <TextBlock Text="{Binding DateNTimeStr}"  Foreground="Green" Grid.Column="0" />
                    <TextBlock Text="{Binding Source}" Foreground="{Binding Source,Converter={StaticResource CoreBusPanelModuleColorConverter}}" Grid.Column="2" Background="{ Binding Source, Converter={StaticResource BackGroundFilterConverterBySource}}" />
                    <TextBlock Text="{Binding Destination}" Foreground="{Binding Destination,Converter={StaticResource CoreBusPanelModuleColorConverter}}" Grid.Column="4" Background="{ Binding Destination, Converter={StaticResource BackGroundFilterConvertorByDestantation}}"  />
                    <TextBlock Text="{Binding Module}" Grid.Column="6" HorizontalAlignment="Center" Background="{ Binding Module, Converter={StaticResource BackGroundFilterByModule}}"   />
                    <TextBlock Text="{Binding Controll}" Grid.Column="8"  Background="{ Binding Controll, Converter={StaticResource BackGRoundFilterByControll}}"  />
                    <TextBlock Text="{Binding Command}" Grid.Column="10" HorizontalAlignment="Center"  Background="{ Binding Command, Converter={StaticResource BackGroundFilterByCommand}}"  />
                    <TextBlock Text="{Binding HSCommand}" Grid.Column="12" HorizontalAlignment="Center"  Background="{ Binding HSCommand, Converter={StaticResource BackGroundFilterByHsCommand}}"   />
                <TextBlock Text="{Binding Data_Str}"  Grid.Column="14"/>                                                                
            </Grid>
        </DataTemplate>
    </ListView.ItemTemplate>
    <ListView.ContextMenu>
        <ContextMenu x:Name="CMMenuCopy">
            <MenuItem x:Name="MCICopyLine" Header="Copy Line" Click="MCICopyLine_Click" ></MenuItem>
            <MenuItem x:Name="MCICopyText" Header="Copy Only Data Array" Click="MCICopyText_Click" ></MenuItem>
            <MenuItem x:Name="MCIClear" Header="Clear" Click="MCIClear_Click"></MenuItem>
        </ContextMenu>
    </ListView.ContextMenu>
</ListView>

不工作的代码多重绑定:

<ListView x:Name="LVGuiCoreBus" ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.HorizontalScrollBarVisibility="Auto" MouseDown="LVGui_MouseDown"  Grid.Row="1" >               
    <ListView.ItemTemplate>
        <DataTemplate>
            <Grid>
                  <Grid.Visibility>
                                    <MultiBinding Converter="{StaticResource MultiValueConvertorVisibility}" UpdateSourceTrigger="PropertyChanged">
                                        <Binding ElementName="Source" Path="Visibility"  UpdateSourceTrigger="PropertyChanged"></Binding>
                                        <Binding ElementName="Destination" Path="Visibility"  UpdateSourceTrigger="PropertyChanged"></Binding>
                                        <Binding ElementName="Module" Path="Visibility"  UpdateSourceTrigger="PropertyChanged"></Binding>
                                        <Binding ElementName="Controll" Path="Visibility"  UpdateSourceTrigger="PropertyChanged"></Binding>
                                        <Binding ElementName="Command" Path="Visibility"  UpdateSourceTrigger="PropertyChanged"></Binding>
                                        <Binding ElementName="HSCommand" Path="Visibility"  UpdateSourceTrigger="PropertyChanged"></Binding>
                                    </MultiBinding>
                                </Grid.Visibility>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="130"></ColumnDefinition>
                    <ColumnDefinition Width="10"></ColumnDefinition>
                    <ColumnDefinition Width="50"></ColumnDefinition>
                    <ColumnDefinition Width="10"></ColumnDefinition>
                    <ColumnDefinition Width="50"></ColumnDefinition>
                    <ColumnDefinition Width="10"></ColumnDefinition>
                    <ColumnDefinition Width="100"></ColumnDefinition>
                    <ColumnDefinition Width="10"></ColumnDefinition>                                                      
                    <ColumnDefinition Width="70"></ColumnDefinition>
                    <ColumnDefinition Width="10"></ColumnDefinition>
                    <ColumnDefinition Width="150"></ColumnDefinition>
                    <ColumnDefinition Width="10"></ColumnDefinition>
                    <ColumnDefinition Width="150"></ColumnDefinition>
                    <ColumnDefinition Width="10"></ColumnDefinition>
                    <ColumnDefinition Width="1*"></ColumnDefinition>
                </Grid.ColumnDefinitions>

                <TextBlock Text="{Binding DateNTimeStr}"  Foreground="Green" Grid.Column="0" />
                    <TextBlock Text="{Binding Source}" Foreground="{Binding Source,Converter={StaticResource CoreBusPanelModuleColorConverter}}" Grid.Column="2" Background="{ Binding Source, Converter={StaticResource BackGroundFilterConverterBySource}}" />
                    <TextBlock Text="{Binding Destination}" Foreground="{Binding Destination,Converter={StaticResource CoreBusPanelModuleColorConverter}}" Grid.Column="4" Background="{ Binding Destination, Converter={StaticResource BackGroundFilterConvertorByDestantation}}"  />
                    <TextBlock Text="{Binding Module}" Grid.Column="6" HorizontalAlignment="Center" Background="{ Binding Module, Converter={StaticResource BackGroundFilterByModule}}"   />
                    <TextBlock Text="{Binding Controll}" Grid.Column="8"  Background="{ Binding Controll, Converter={StaticResource BackGRoundFilterByControll}}"  />
                    <TextBlock Text="{Binding Command}" Grid.Column="10" HorizontalAlignment="Center"  Background="{ Binding Command, Converter={StaticResource BackGroundFilterByCommand}}"  />
                    <TextBlock Text="{Binding HSCommand}" Grid.Column="12" HorizontalAlignment="Center"  Background="{ Binding HSCommand, Converter={StaticResource BackGroundFilterByHsCommand}}"   />
                <TextBlock Text="{Binding Data_Str}"  Grid.Column="14"/>                                                                
            </Grid>
        </DataTemplate>
    </ListView.ItemTemplate>
    <ListView.ContextMenu>
        <ContextMenu x:Name="CMMenuCopy">
            <MenuItem x:Name="MCICopyLine" Header="Copy Line" Click="MCICopyLine_Click" ></MenuItem>
            <MenuItem x:Name="MCICopyText" Header="Copy Only Data Array" Click="MCICopyText_Click" ></MenuItem>
            <MenuItem x:Name="MCIClear" Header="Clear" Click="MCIClear_Click"></MenuItem>
        </ContextMenu>
    </ListView.ContextMenu>
</ListView>
 public class MultiValueConvertorVisibility : IMultiValueConverter
 {
 public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        bool x = System.Convert.ToBoolean(values[0]);
        if (x)
        {
            return System.Windows.Visibility.Visible;
        }
        else
        {
            return System.Windows.Visibility.Collapsed;
        }
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
 }

【问题讨论】:

  • 需要设置MultiBinding的Converter。
  • 什么是多重绑定转换器?并且为了达到元素应该是另一个转换器,你能举个例子吗
  • 您已经在 MultiBinding 内的 Binding 上设置了转换器。与此类似,MultiBinding 本身也有一个 Converter 属性,您必须在其中分配一个实现 IMultiValueConverter 接口的对象。
  • 能否给我一个代码示例

标签: c# wpf multibinding


【解决方案1】:

从概念上讲,您缺少的最重要的部分是IMultiValueConverter,因为可见性只是一个值,在一天结束时,您希望您的网格可见或不可见,因此您必须告诉多重绑定如何将多个值合二为一。

这是一个如何让多重绑定工作的示例:

网格:

<Window x:Class="WpfApp1.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:local="clr-namespace:WpfApp1"
    mc:Ignorable="d"
    Title="MainWindow" Height="450" Width="800">
<Window.Resources>
    <local:MultiValueConverter x:Key="MyCustomConvertor"/>
</Window.Resources>


<Grid ShowGridLines="True">
    <Grid.Visibility>
        <MultiBinding Converter="{StaticResource MyCustomConvertor}" UpdateSourceTrigger="PropertyChanged">
            <Binding Path="Visibility"/>
        </MultiBinding>
    </Grid.Visibility>
    <Grid.RowDefinitions>
        <RowDefinition Height="100"/>
        <RowDefinition Height="100"/>
        <RowDefinition Height="100"/>
    </Grid.RowDefinitions>
</Grid>

您绑定到的 Viewmodel

using System.ComponentModel;
using System.Windows;

namespace WpfApp1
{
    class VM : INotifyPropertyChanged
    {
        #region WPF integration properties
        public event PropertyChangedEventHandler PropertyChanged;

        // Create the OnPropertyChanged method to raise the event
        protected void OnPropertyChanged(string name)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }
        #endregion

        private Visibility _visibility = Visibility.Hidden;
        public Visibility Visibility
        {
            get { return _visibility; }
            set
            {
                _visibility = value;
                OnPropertyChanged(nameof(Visibility));
            }
        }
    }
}

最后是 MultiValueConverter 将多个可见性绑定转换为一个:

using System;
using System.Linq;
using System.Windows;
using System.Windows.Data;

namespace WpfApp1
{
    class MultiValueConverter : IMultiValueConverter
    {

        public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {

            if (values.Contains(Visibility.Collapsed))
            {
                return Visibility.Collapsed;
            }

            if (values.Contains(Visibility.Hidden))
            {
                return Visibility.Hidden;
            }

            return Visibility.Visible;
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }

    }
}

您可以在转换器中放置您认为合适的任何逻辑,我只是​​对不同的可见性类型施加了一种层次结构。

【讨论】:

  • 嘿@RubenBohnet 道歉,但我不觉得这是正确的。 ViewModel 通常不应该控制视图状态,换句话说,将 Visibility 放在 ViewModel 中被认为是不好的做法。但是,如果您这样做,则可以将所有逻辑放在 ViewModel 中并删除转换器。它需要是其中之一。我强烈建议坚持使用转换器进行可见性更改。一个简单的 IMultiValueConverter 就足够了。希望您将此评论视为建议,而不是强烈批评。我的意思是好的。 ViewModel 不应假定视图状态或控制视图。
  • 这里显示的直接映射只是为了避免额外的抽象步骤,这不会增加答案。可以很容易地假设视图模型是一个节点,它包含一个沿Active 行的布尔值,它首先将由转换器转换为可见性。该示例将尊重 MVVM 模型中的职责,但我认为这无助于 OP 更好地理解他的问题的答案。
  • 另外:感谢您花时间改进我的编程!
猜你喜欢
  • 1970-01-01
  • 2011-06-14
  • 1970-01-01
  • 1970-01-01
  • 2014-03-31
  • 2018-07-28
  • 2013-12-09
  • 2011-08-31
  • 2016-01-31
相关资源
最近更新 更多