通过INotify和MVVM将字符串从一个用户控件传递到第二个用户控件 [英] passing a string from one user control to a second user control via INotify wihtin MVVM

查看:56
本文介绍了通过INotify和MVVM将字符串从一个用户控件传递到第二个用户控件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

通过INotify将字符串从一个用户控件传递到第二个用户控件时遇到一些问题。

I am having some issues with passing a string from one user control to a second user control via INotify.

在视图中,我有一个绑定到的列表框每当用户在用户控件内的文本框中键入值时,便会向类型为SearchHistory的字符串类型的ObservableCollection传递一个值,并将其输入到集合中并在列表框控件中显示(有些输入的术语历史)。这很好。

Within the view I have a listbox which is bound to a ObservableCollection of type string titled SearchHistory whenever a user types a value into a textbox which is within a user control I pass the value typed into the collection and display it within the listbox control ( somewhat of a history of terms entered). This works fine.

我现在试图选择列表框项,并通过INotifyPropertyChanged将其传递回控件中的文本框。当我看到选择的值被传递回视图模型中的属性时,它并没有使用新的选择的值更新视图中的文本框。

I am now trying to select the listbox item and pass it back to the textbox within the control via INotifyPropertyChanged. While I see the value selected being passed back to the property within the view model it is not updating the textbox within the view with the new selected value.

在我的视图中,我列表框项目具有以下xaml

Within my view I have the following xaml for the listbox item

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

在视图代码的内部,我有以下内容(由于该功能,我选择将其放置在代码中是特定于视图的,它是在两个控件之间传递字符串。我认为这不需要作为命令包含在viewmodel中,但是如果是这样,请让我知道否则)

Within the view codebehind I have the following ( I opted to place this in the code behind since the functionality was specific to the view in passing the string between two controls. I don't think this needs to be in the viewmodel as a command but if so please let me know otherwise)

    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

Within the ViewModel I also have the public property SearchTerm declared

        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
       }

该值从视图传递到视图模型,并且我看到上面的属性已更新,但是当它击中绑定到UI的部分时,UI中什么也没有发生。

As I stated when I step through this the value is passed from the view to the view model and I see the above property updated however when it hits the section that binds to the UI nothing happens in the UI.

下面是包含文本块的usercontrol的部分xaml(不包括网格包装和标头上下文)。由于我从父视图继承了数据上下文,因此控件内未设置任何数据上下文。

Below is the partial (I excluded the grid wrapper and header context) xaml for the usercontrol that contains the textblock. No data context is set within the control as I inherit the data context from the parent view.

<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>

最后将控件放置在主视图中

And finally the control as it is placed in the main view

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

任何提示或建议都值得赞赏。
预先谢谢

Any tips or suggestions are appreciated. Thank you in advance

推荐答案

在解决此问题时,我发现问题出在试图将字符串传回属性以及我最初将值存储在通用集合中的方式。以下是我解决问题的方法。

Working through this, I found the issue to be in attempting to pass a string back to the property as well as how I was originally storing my values in a generic collection. Below is how I resolved the issue.

我们首先从搜索用户控件中的xaml开始。此控件包含我要更新的文本字段。

We'll start first with the xaml within my search user control. This control contained the text field I wanted updated.

<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中,我声明了一个新集合

Within the ViewModel I declared a new collection

委托命令

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);
    }

从模型内部,然后我创建了一个将字符串添加到集合中的方法

From within the Model I then created a method to add the strings to my collection

委托命令

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);                 
    }

通过这种方式,我能够将集合推回用户界面,然后将此绑定到Listbox

Taking this route I was able to push the collection back to the UI and then bind this to Listbox

然后在我的视图中,我便能够使用更改选择的事件来更新搜索历史可观察的集合。虽然我不确定100%,但我认为问题与可观察的集合如何处理NotificationChanged事件有关。

then within my View I was able to then use the selection changed event to update the Search History Observable Collection. While I am not 100% certain I think the issue was related to how the observable collection handles NotificationChanged events. If anyone has any additional insight to this I would appreciate it.

seach.xaml.cs后面的代码

seach.xaml.cs code behind

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的哑属性

*Note for clarity the SearchHistoryModely only contained one dumb property titled SearchHistoryString

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

这里主要要注意的是,我将列表框项目投射到了集合/财产。由于这些项目只有在其中包含对象的情况下才是不可见的,因此我没有测试空值,但是我想我稍后再回过头来更新它,只是为了保持整洁。

The main thing to note here is that I cast the Listbox Item to my collection / property. Since the items would never be visible unless they have an object within them I did not test for null values however I think I'll go back later and update that just for tidiness.

现在进行这些更改使我可以将列表框集合中的项目传递回textBlock字段(反之亦然)。

Making these changes now allow for me to pass items from the listbox collection back to the textBlock field ( or vice versa).

我欢迎其他任何替代方法或更多方法简化的解决方案。
谢谢

I would welcome any other alternative or more streamlined solutions. Thank you

这篇关于通过INotify和MVVM将字符串从一个用户控件传递到第二个用户控件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆