передача строки от одного пользовательского элемента управления другому пользовательскому элементу управления через INotify с помощью MVVM - PullRequest
0 голосов
/ 24 мая 2011

У меня возникли проблемы с передачей строки из одного пользовательского элемента управления во второй пользовательский элемент управления через INotify.

В представлении у меня есть список, связанный с ObservableCollection типа string с названием SearchHistory, когда пользователь вводит значение в текстовое поле, которое находится внутри пользовательского элемента управления, я передаю значение, введенное в коллекцию, и отображаю его в списке. контроль (немного истории введенных терминов). Это отлично работает.

Я сейчас пытаюсь выбрать элемент списка и передать его обратно в текстовое поле в элементе управления через INotifyPropertyChanged. Хотя я вижу, что выбранное значение передается обратно свойству в модели представления, оно не обновляет текстовое поле в представлении новым выбранным значением.

На мой взгляд, у меня есть следующий xaml для элемента списка

<ListBox Margin="0,0,1,0"
                         Background="{x:Null}"
                         BorderBrush="{x:Null}"
                         BorderThickness="0"
                         ItemsSource="{Binding SearchHistory}" 
                         SelectionChanged="ListBox_SelectionChanged" />

В коде представления у меня есть следующее (я решил разместить это в коде сзади, поскольку функциональность была специфична для представления при передаче строки между двумя элементами управления. Я не думаю, что это должно быть в модели представления как команда, но если да, пожалуйста, дайте мне знать иначе)

    public partial class viewSearch : Page
{
    private SearchViewModel _ViewModel;

    #region Constructor
    public viewSearch()
    {
        InitializeComponent();
        CloseFilterPanel();
        CloseHistoryPanel();
        CloseSaveSearchPanel();
        this._ViewModel = new SearchViewModel();
        this.DataContext = this._ViewModel;
    }

... отредактировано для краткости

private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        if(((ListBox)sender).SelectedItem != null)
        _ViewModel.SearchTerm = (((ListBox)sender).SelectedItem.ToString());
        this.NotifyPropertyChanged(_ViewModel.SearchTerm);
    }

В ViewModel у меня также объявлено открытое свойство SearchTerm

        public string SearchTerm
    {
        get
        {
            return this._SearchTerm;
        }
        set
        {
            if (this._SearchTerm == value)
                return;

            // Set the new value and notify
            this._SearchTerm = value;
            this.NotifyPropertyChanged("SearchTerm"); //this binds to UI search textbox
       }

Как я уже говорил, когда я прохожу этот шаг, значение передается из представления в модель представления, и я вижу, что вышеупомянутое свойство обновляется, однако, когда оно попадает в раздел, связанный с пользовательским интерфейсом, в пользовательском интерфейсе ничего не происходит.

Ниже приведен частичный (я исключил оболочку сетки и контекст заголовка) xaml для usercontrol, который содержит текстовый блок. В элементе управления не задан контекст данных, поскольку я наследую контекст данных из родительского представления.

<TextBox x:Name="txtSearchField"
        Grid.Column="0"
        Margin="5,3,5,1.333"
        ap:AttachedProperties.InitialFocus="True"
        FontSize="16"
        KeyDown="txtSearchField_KeyDown"
        Padding="2,5,10,1"
        Style="{StaticResource SearchTxtBoxStyle}"
        Text="{Binding SearchTerm, Mode=TwoWay}"
        TextAlignment="Right"
        ToolTipService.ToolTip="{StaticResource TTsearchField}">
        <i:Interaction.Triggers>
            <ei:KeyTrigger FiredOn="KeyUp" Key="Enter">
                <i:InvokeCommandAction Command="{Binding GetSearchResultCommand, Mode=OneWay}"/>
            </ei:KeyTrigger>
        </i:Interaction.Triggers>           
    </TextBox>

И, наконец, элемент управления, размещенный на главном экране

<srch:SearchControl x:Name="ucSearchControl" DataContext="{Binding}" Grid.Row="0" />

Любые советы или предложения приветствуются. Заранее спасибо

Ответы [ 3 ]

0 голосов
/ 25 мая 2011

это не проверено, но когда вы просто хотите установить выбранный элемент из списка в свойстве textbox.text, это будет работать: (я предполагаю, что имя вашего TextBox - txtSearch)

 <ListBox Margin="0,0,1,0"
                     Background="{x:Null}"
                     BorderBrush="{x:Null}"
                     BorderThickness="0"
                     ItemsSource="{Binding SearchHistory}" 
                     SelectedItem="{Binding ElementName=txtSearch, Path=Text, Mode=OneWayToSource}" />
0 голосов
/ 25 мая 2011

Если я правильно понимаю, есть очень простой способ достичь того, что вы хотите сделать, в стиле "MVVM".

Вы можете иметь SelectedItem в ListBox "TwoWay", привязанном к свойству в ViewModel первого элемента управления. В установщике этого свойства вы можете отправить сообщение , скажем SearchTermSelectedMessage, которое будет получено ViewModel другого элемента управления, и соответственно установить свойство, которое будет обновлять интерфейс. Для этого вы можете использовать MVVMLight Messenger объект.

Надеюсь, это поможет.

0 голосов
/ 25 мая 2011

Работая с этим, я обнаружил, что проблема заключается в попытке передать строку обратно в свойство, а также в том, как я изначально хранил свои значения в универсальной коллекции. Ниже описано, как я решил проблему.

Сначала мы начнем с xaml в моем поисковом пользовательском элементе управления. Этот элемент управления содержал текстовое поле, которое я хотел обновить.

<TextBox x:Name="txtSearchField"
        Grid.Column="0"
        Margin="5,3,5,1.333"
        ap:AttachedProperties.InitialFocus="True"
        FontSize="16"
        KeyDown="txtSearchField_KeyDown"
        Padding="2,5,10,1"
        Style="{StaticResource SearchTxtBoxStyle}"
        Text="{Binding SearchTerm, Mode=TwoWay}"
        TextAlignment="Right"
        ToolTipService.ToolTip="{StaticResource TTsearchField}">
        <i:Interaction.Triggers>
            <ei:KeyTrigger FiredOn="KeyUp" Key="Enter">
                <i:InvokeCommandAction Command="{Binding GetSearchResultCommand, Mode=OneWay}"/>
            </ei:KeyTrigger>
        </i:Interaction.Triggers>           
    </TextBox>

В ViewModel я объявил новую коллекцию

команда делегата

private ObservableCollection<SearchHistoryModel> _SearchHistory = new ObservableCollection<SearchHistoryModel>();

Создал мою собственность

public ObservableCollection<SearchHistoryModel> SearchHistory
    {

        get
        {
            return this._SearchHistory;
        }
        private set
        {
            if (this._SearchHistory == value)
                return;
            this._SearchHistory = value;
            this.NotifyPropertyChanged("SearchHistory");
        }
    }

И команда для модели

private void GetSearchResultCommandExecute(object parameter)
    {
        //query
       this.SearchResults = this._DataModel.GetSearchResults(this.SearchTerm);
        //search history items
      this.SearchHistory = this._DataModel.AddSearchHistoryItem(this.SearchTerm);
    }

Затем внутри модели я создал метод для добавления строк в мою коллекцию

команда делегата

private ObservableCollection<SearchHistoryModel> SearchHistory = new ObservableCollection<SearchHistoryModel>();
* * Метод тысячу двадцать-один * * одна тысяча двадцать-два
public ObservableCollection<SearchHistoryModel>AddSearchHistoryItem(string searchHistoryItem)
    {
        SearchHistoryModel shm = new SearchHistoryModel();
        shm.SearchHistoryString = searchHistoryItem.ToString();
        SearchHistory.Add(shm);
        return this.SearchHistory;
            //this.SearchHistory = new ObservableCollection<SearchHistoryModel>();
            //this.SearchHistory.Add(searchHistoryItem);                 
    }

По этому маршруту я смог перенести коллекцию обратно в пользовательский интерфейс и затем связать ее со списком

затем в моем представлении я смог затем использовать событие выбора измененного, чтобы обновить наблюдаемую коллекцию истории поиска. Хотя я не уверен на 100%, я думаю, что проблема была связана с тем, как наблюдаемая коллекция обрабатывает события NotificationChanged. Если у кого-то есть дополнительное понимание этого, я был бы признателен.

seach.xaml.cs код позади

private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        if (((ListBox)sender).SelectedItem != null)
            _ViewModel.SearchTerm = (((ListBox)sender).SelectedItem as SearchHistoryModel).SearchHistoryString.ToString();
        this.NotifyPropertyChanged(_ViewModel.SearchTerm);
    }

* Обратите внимание, что SearchHistoryModely содержит только одно немое свойство с именем SearchHistoryString

 public class SearchHistoryModel
{
    public string SearchHistoryString { get; set; }
}

Главное, что следует отметить, это то, что я бросил элемент списка в свою коллекцию / собственность. Так как элементы никогда не были бы видимы, если бы у них не было объекта внутри, я не проверял на нулевые значения, однако я вернусь позже и обновлю это только для аккуратности.

Внесение этих изменений теперь позволяет мне передавать элементы из коллекции списка обратно в поле textBlock (или наоборот).

Я бы приветствовал любые другие альтернативные или более рациональные решения. Спасибо

...