ItemsControl文本框textchange事件如何调用?

时间:2012-03-16 12:48:14

标签: wpf c#-4.0 mvvm binding user-controls

一般TextBox控制TextChanged事件正在运行,但在ItemsControl中,TextBox TextChanged事件未被解雇,我该怎么做。我试图通过使用以下代码来实现,但我没有得到我想要的结果。

那么,我做错了什么?

查看

<Window x:Class="SoniSoft.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:ff="clr-namespace:SoniSoft"
        Title="Window1" Height="300" Width="300">

    <Window.DataContext>
                <ff:ViewModels/>
            </Window.DataContext>
    <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="38"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
    <TextBox Grid.Row="0" ff:TextBoxBehaviour.TextChangedCommand="{Binding TextChanged}"  />

    <ItemsControl Margin="7,0,0,0" Grid.Row="3" ItemsSource="{Binding Path=ViewModelSearchResults}" x:Name="list">
                <ItemsControl.ItemTemplate>
                    <DataTemplate >
                        <Grid>
                            <TextBox  ff:TextBoxBehaviour.TextChangedCommand="{Binding TextChanged}" Text="{Binding Path=CategoryName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" FontSize="14" FontWeight="Normal" x:Name=" TextBoxCategoryName" />
                        </Grid>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        </Grid>
    </Window>

查看模型

class ViewModels :ViewModelBase
            {
                public ObservableCollection<Category> AllCategorys = new ObservableCollection<Category>();
                DatabaseDataContext db = new DatabaseDataContext();
                private ListCollectionView _objViewModelSearchResults;
                public ListCollectionView ViewModelSearchResults
                {
                    get { return _objViewModelSearchResults; }
                    set
                    {
                        _objViewModelSearchResults = value;
                        OnPropertyChanged("ViewModelSearchResults");
                    }
                }
                public ViewModels()
                {
                    AllCategorys.Clear();
                    foreach (var item in db.Categories.OrderBy(c => c.CategoryName))
                    {
                        AllCategorys.Add(item);
                    }
                    ViewModelSearchResults = new ListCollectionView(AllCategorys);
                }
                public ICommand TextChanged
                {
                    get
                    {
                        //  this is very lazy: I should cache the command!
                        return new TextChangedCommand();
                    }
                }
        private class TextChangedCommand : ICommand
                {
                    public event EventHandler CanExecuteChanged;
                    public void Execute(object parameter)
                    {
                        MessageBox.Show("Text Changed");
                    }

                    public bool CanExecute(object parameter)
                    {
                        return true;
                    }
                }
            }

的DependencyProperty

class EventBehaviourFactory
                {
                    public static DependencyProperty CreateCommandExecutionEventBehaviour(RoutedEvent routedEvent, string propertyName, Type ownerType)
                    {
                        DependencyProperty property = DependencyProperty.RegisterAttached(propertyName, typeof(ICommand), ownerType,
                                                                           new PropertyMetadata(null,
                                                                               new ExecuteCommandOnRoutedEventBehaviour(routedEvent).PropertyChangedHandler));

                        return property;
                    }
    private class ExecuteCommandOnRoutedEventBehaviour : ExecuteCommandBehaviour
                    {
                        private readonly RoutedEvent _routedEvent;

                        public ExecuteCommandOnRoutedEventBehaviour(RoutedEvent routedEvent)
                        {
                            _routedEvent = routedEvent;
                        }

                        /// <summary>
                        /// Handles attaching or Detaching Event handlers when a Command is assigned or unassigned
                        /// </summary>
                        /// <param name="sender"></param>
                        /// <param name="oldValue"></param>
                        /// <param name="newValue"></param>
                        protected override void AdjustEventHandlers(DependencyObject sender, object oldValue, object newValue)
                        {
                            UIElement element = sender as UIElement;
                            if (element == null) { return; }

                            if (oldValue != null)
                            {
                                element.RemoveHandler(_routedEvent, new RoutedEventHandler(EventHandler));
                            }

                            if (newValue != null)
                            {
                                element.AddHandler(_routedEvent, new RoutedEventHandler(EventHandler));
                            }
                        }

                        protected void EventHandler(object sender, RoutedEventArgs e)
                        {
                            HandleEvent(sender, e);
                        }
                    }

                    internal abstract class ExecuteCommandBehaviour
                    {
                        protected DependencyProperty _property;
                        protected abstract void AdjustEventHandlers(DependencyObject sender, object oldValue, object newValue);

                        protected void HandleEvent(object sender, EventArgs e)
                        {
                            DependencyObject dp = sender as DependencyObject;
                            if (dp == null)
                            {
                                return;
                            }

                            ICommand command = dp.GetValue(_property) as ICommand;

                            if (command == null)
                            {
                                return;
                            }

                            if (command.CanExecute(e))
                            {
                                command.Execute(e);
                            }
                        }

                        /// <summary>
                        /// Listens for a change in the DependencyProperty that we are assigned to, and
                        /// adjusts the EventHandlers accordingly
                        /// </summary>
                        /// <param name="sender"></param>
                        /// <param name="e"></param>
                        public void PropertyChangedHandler(DependencyObject sender, DependencyPropertyChangedEventArgs e)
                        {
                            // the first time the property changes,
                            // make a note of which property we are supposed
                            // to be watching
                            if (_property == null)
                            {
                                _property = e.Property;
                            }

                            object oldValue = e.OldValue;
                            object newValue = e.NewValue;

                            AdjustEventHandlers(sender, oldValue, newValue);
                        }
                    }

                }

             class TextBoxBehaviour
                {
                    public static readonly DependencyProperty TextChangedCommand = EventBehaviourFactory.CreateCommandExecutionEventBehaviour(TextBox.TextChangedEvent, "TextChangedCommand", typeof(TextBoxBehaviour));

                    public static void SetTextChangedCommand(DependencyObject o, ICommand value)
                    {
                        o.SetValue(TextChangedCommand, value);
                    }

                    public static ICommand GetTextChangedCommand(DependencyObject o)
                    {
                        return o.GetValue(TextChangedCommand) as ICommand;
                    }
                 }

1 个答案:

答案 0 :(得分:0)

这是问题所在。您正在ItemTemplate中设置命令。因此它绑定到Category中的ListCollectionView对象。现在,这是不包含任何更改文本命令的对象。包含TextChanged命令的内容是UserControl的DataContext,您需要将其绑定到该文件。

现在有一种方法可以解决,其名称为Ancestor RelativeSource。当我使用silverlight时,它可能会有所不同,但这行代码应该可以。

修改

实际的行应该是。这是因为它是一个窗口,你需要有DataContext(viewmodel),然后是属性TextChanged

<TextBox ff:TextBoxBehaviour.TextChangedCommand="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}, Path=DataContext.TextChanged}" />