自动完成遵循MVVM模式的TextBox

时间:2013-06-20 15:06:36

标签: wpf data-binding mvvm autocomplete combobox

我有一个文本框,我想将其设为自动填充文本框。 我输入文本框时要显示的数据来自我的数据网格。我的datagrid有4列,我可以从datagrid中选择任何列。

这是我的文本框

         <TextBox Margin="0,93,39,18" Grid.Column="1" HorizontalAlignment="Right" Width="325">
            <TextBox.Style>
                <Style TargetType="TextBox">
                    <Style.Triggers>
                        <Trigger Property="Text" Value="">
                            <Setter Property="Background" Value="{StaticResource SearchHint}"/>
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </TextBox.Style>
        </TextBox>

数据网格

    <DataGrid Name="Datagrid"  ItemsSource="{Binding Messages}" Margin="4,0,380,413" Grid.Row="1" AutoGenerateColumns="False"  
    IsReadOnly="True"  RowBackground="WhiteSmoke" >

我用谷歌搜索,我得到的大部分样本都没有遵循WPF / MVVM模式。我要做的是将文本块数据绑定到网格项目。有人可以通过给我点到哪里开始帮助我。

1 个答案:

答案 0 :(得分:8)

有很多不同的方法可以解决这个问题,但可以说最突出的是可编辑的组合框策略(他们在微软的WPF考试中提出了很多关于这一问题的问题,这完全是IGVM的MVVM模式,但这是另一个问题。天)。我举一个例子来帮助你入门。第一步是编写组合框和数据网格......

  <StackPanel>
            <ComboBox
             IsEditable="True"
             IsTextSearchEnabled="True"
             IsSynchronizedWithCurrentItem="True"
             SelectedItem="{Binding MySelectedItem, Mode=TwoWay}"
             ItemsSource="{Binding MyItems}"
            >
                <ComboBox.InputBindings>
                    <KeyBinding  Key="Enter" Command="{Binding NotImplementedCommand}"/>
                </ComboBox.InputBindings>
            </ComboBox>
                <DataGrid
                ItemsSource="{Binding DriveList}"
                AutoGenerateColumns="True"
                />
        </StackPanel>

然后创建一个ViewModel ...

public class ViewModel :INotifyPropertyChanged
{
    public ObservableCollection<string> MyItems { get; set; }
    public ObservableCollection<DriveInfo> DriveList { get; set; }
    public event PropertyChangedEventHandler PropertyChanged;
    public ViewModel()
    {
        MyItems = new ObservableCollection<string>();
        DriveList = new ObservableCollection<DriveInfo>();
        foreach (DriveInfo di in DriveInfo.GetDrives())
        {
            DriveList.Add(di);
        }
        DriveListCollectionChanged(null, null);
        DriveList.CollectionChanged += DriveListCollectionChanged;

    }
    void DriveListCollectionChanged(object sender, 
                        System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        MyItems.Clear();
        List<string> temp = new List<string>();
        foreach (DriveInfo di in DriveList)
        {// add 4 columns from the DataGrid to the auto complete source
            temp.Add(di.Name);
            temp.Add(di.DriveType.ToString());
            if (di.IsReady)
            {
                temp.Add(di.DriveFormat);
                temp.Add(di.TotalSize.ToString());
                temp.Add(di.AvailableFreeSpace.ToString());
            }
        }
        foreach (string s in temp.Distinct())
        {
            MyItems.Add(s);
        }
    }
    private string _mySelectedItem;
    public string MySelectedItem
    {
        get { return _mySelectedItem; }
        set
        {
            if (value != _mySelectedItem)
            {
                _mySelectedItem = value;
                OnPropertyChanged("MySelectedItem");
            }
        }
    }
    private void OnPropertyChanged(string s)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(s));
        }
    }
}

此示例中断DataGrid源更改的事件,并使用MULTIPLE列填充组合框。如果你只是做一个列,这里的解决方案会有所不同。还有一些绑定的esoterica,你可以自动将组合框绑定到数据,但是根据你的要求以及你想要将多列异构字符串添加到组合框中的意图,它的教学价值是有问题的。

在部署应用之前,您需要更好地优化事件处理程序,因为上面显示的仅用于演示目的。

要将其连接起来,请将此(或其备用)放入您的Xaml ......

   <Window.Resources>
        <wpfApplication3:ViewModel  x:Key="ViewModel"/>
    </Window.Resources>
    <Grid DataContext="{StaticResource ViewModel}">
        <!-- your xaml -->
    </Grid>  

上面的ViewModel类是一个符合MVVM的解决方案,您可以将此类的实例绑定到呈现视图的DataContext。