WPF - 如何为特定场景绑定正确的方法?

时间:2015-09-06 00:48:04

标签: c# wpf wpf-controls

我是WPF的新手(从WinForms迁移)。我正在尝试将一些场景从WinForms应用程序转移到WPF应用程序:

  1. 一个窗口有一个包含3列的ListView控件。
  2. 有一个按钮可以向ListView添加新行。
  3. 第一列和第二列包含ComboBox控件。
  4. 第三列必须包含不同的控件,但一次只能看到一个。哪一个是可见的,它取决于第一列中ComboBox的选定值。
  5. 每次用户从第一列的ComboBox中选择值时,第二列的ComboBox内容都会更改。
  6. 一般情况是:用户从第一个ComboBox中的类型列表中选择一个类型,之后第二个ComboBox将其内容更改为所选类型的受支持操作列表,此时第三列必须更改其内容显示支持该类型输入的控件。

    我知道如何使用WinForms实现它,但我还不知道如何使用WPF来实现它。有人可以帮助我实现它,还是任何人都可以帮助实现有助于实现它的信息?

    到目前为止我有代码:

    public class ViewModelBase : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
    
        protected virtual void OnPropertyChanged(string propertyName)
        {
            OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
        }
    
        protected virtual void OnPropertyChanged(PropertyChangedEventArgs args)
        {
            if (PropertyChanged != null) PropertyChanged(this, args);
        }
    }
    
    public class RecordFilter : ViewModelBase
    {
        private static readonly ObservableCollection<KeyValuePair<PropertyInfo, string>> ColumnAliases =
            new ObservableCollection<KeyValuePair<PropertyInfo, string>>(Card.ColumnAliases);
    
        private KeyValuePair<PropertyInfo, string> _currentSelectedProperty;
    
        public IEnumerable<OperationInfo> Operations
        {
            get
            {
                return Operations.GetOperationInfosForType(GetTypeUnwrapNullable(SelectedProperty.Key.PropertyType));
            }
        }
    
        public OperationInfo SelectedOperation { get; set; }
    
        public KeyValuePair<PropertyInfo, string> SelectedProperty
        {
            get { return _currentSelectedProperty; }
            set
            {
                _currentSelectedProperty = value;
    
                OnPropertyChanged("Operations");
            }
        }
    
        public ObservableCollection<KeyValuePair<PropertyInfo, string>> Properties
        {
            get { return ColumnAliases; }
        }
    
        //DateTime or int or float, depends on the selected property type
        //public object PropertyValue { get; set; }
    }
    

    这是XAML代码:

    <Window
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:Converters="clr-namespace:App.Converters" x:Class="App.DialogWindows.CardFilterWindow"
            Title="Search filters" Height="347" Width="628" x:Name="wdw" ShowInTaskbar="False" WindowStartupLocation="CenterScreen">
        <Window.Resources>
            <Converters:NotNullObjectToEnabledConverter x:Key="NotNullObjectToEnabledConverter"/>
        </Window.Resources>
        <DockPanel>
            <StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal" HorizontalAlignment="Center" Height="Auto">
                <Button x:Name="bnOK" Margin="5" Width="41" Content="OK" IsDefault="True" Click="bnOK_Click"/>
                <Button x:Name="bnCancel" Margin="5" Content="Отмена" IsCancel="True"/>
            </StackPanel>
            <ListView ItemsSource="{Binding Filters, ElementName=wdw}" Name="LvExpr" DataContext="{Binding Filters, ElementName=wdw}">
                <ListView.Resources>
                    <Style TargetType="{x:Type ListViewItem}">
                        <Setter Property="HorizontalContentAlignment" Value="Stretch" />
                    </Style>
                </ListView.Resources>
                <ListView.View>
                    <GridView>
                        <GridViewColumn Header="Alias" Width="210">
                            <GridViewColumn.CellTemplate>
                                <DataTemplate>
                                    <ComboBox VerticalAlignment="Center"
                                        ItemsSource="{Binding Properties}"
                                        DisplayMemberPath="Value"
                                        SelectedValue="{Binding SelectedProperty, Mode=TwoWay}"
                                        />
                                </DataTemplate>
                            </GridViewColumn.CellTemplate>
                        </GridViewColumn>
                        <GridViewColumn Header="Operation" Width="150">
                            <GridViewColumn.CellTemplate>
                                <DataTemplate>
                                    <ComboBox VerticalAlignment="Center"
                                        ItemsSource="{Binding Operations}"
                                        DisplayMemberPath="OperationAlias"
                                        SelectedValue="{Binding SelectedOperation, Mode=TwoWay}"
                                    />
                                </DataTemplate>
                            </GridViewColumn.CellTemplate>
                        </GridViewColumn>
                        <GridViewColumn Header="Value" Width="100">
                            <GridViewColumn.CellTemplate>
                                <DataTemplate>
                                    <TextBox Text="ValidatesOnDataErrors=True}" />
                                </DataTemplate>
                            </GridViewColumn.CellTemplate>
                        </GridViewColumn>
                        <GridViewColumn Width="33">
                            <GridViewColumn.CellTemplate>
                                <DataTemplate>
                                    <Button Tag="{Binding Mode=OneWay}" Click="BnDelete_Click" ToolTip="Delete filter">
                                        <Image Source="delete.ico" Height="16" Width="16"/>
                                    </Button>
                                </DataTemplate>
                            </GridViewColumn.CellTemplate>
                            <GridViewColumnHeader>
                                <DataGridCell>
                                    <Button Click="ButtonAdd_Click" Height="22" Padding="0" ToolTip="Add filter">
                                        <Image Source="plus.ico" Focusable="False"/>
                                    </Button>
                                </DataGridCell>
                            </GridViewColumnHeader>
                        </GridViewColumn>
                    </GridView>
                </ListView.View>
            </ListView>
        </DockPanel>
    </Window>

1 个答案:

答案 0 :(得分:1)

在视图模型中,设置列表属性,并在所选值更改时(通过INotifyPropertyChanged.PropertyChanged事件)相应地过滤掉它们。

有关综合示例,请参阅this帖子。它使用一种名为MVVM的技术,广泛用于WPF,代表ModelViewViewModel。我强烈建议您学习这种技术并在XAML相关项目中使用它。 Here是网上许多人的快速入门教程。