簡體   English   中英

如何從ViewModel更新視圖

[英]How to update the View from a ViewModel

我有一個viewmodel ProductsViewModel ,其中一種方法將新產品添加到它存儲的ProductList中。 我目前有一個ListBox綁定到ProductList 我通過將按鈕綁定到一個簡單的Command來添加新產品,該Command調用了viewmodel上的相關方法。

當視圖模型無法與視圖“對話”時,如何修改視圖以選擇已添加到ListBox的新產品並向下滾動到新項目?

編輯

請注意,我不希望每次將新項目添加到列表框中時都自動選擇最后一個項目,因為當我將項目導入到要避免的列表框中時,它將選擇最后一個項目。

在ViewModel'SelectedProduct'中創建一個屬性(顯然,它需要提高屬性。在將新產品添加到ProductList之后,還要使用此新產品更新SelectedProduct。在視圖中,將ListBox的SelectedItem綁定到CurrentProduct。

通常,實現此目標的最佳方法是行為。 該實現可能取決於您的特定要求,但是我將在此處提供一個通用示例,該示例演示如何使視圖模型觸發ListBox滾動到您選擇的特定項目。

首先,您需要一種從視圖模型到視圖的通信方式,您不能直接綁定到XAML中的事件,而是可以將事件封裝在包裝器中並綁定到該包裝器:

public class ListBoxScrollHandler
{
    public event Action<object> ScrollEvent;

    public void ScrollTo(object item)
    {
        if (this.ScrollEvent != null)
            this.ScrollEvent(item);
    }
}

該類包含一個我們的行為可以綁定到的事件,以及一個我們的視圖模型可以調用的ScrollTo方法。 對於該視圖,我們只需要創建一個簡單的列表框,用數字(實際上是字符串)填充這個列表框,並使用一個按鈕強制我們滾動到內容為“ 500”的元素:

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition />
    </Grid.RowDefinitions>

    <Button Content="Scroll to 500" HorizontalAlignment="Left" VerticalAlignment="Top" Command="{Binding ScrollCommand}" CommandParameter="500" />
    <ListBox Grid.Row="1" ItemsSource="{Binding MyItems}" SelectedItem="{Binding CurrentItem}" ScrollViewer.VerticalScrollBarVisibility="Visible">
        <i:Interaction.Behaviors>
            <behaviors:ListBoxScrollBehavior ScrollHandler="{Binding ScrollHandler}" />
        </i:Interaction.Behaviors>
    </ListBox>
</Grid>

如您所見,我已經通過Blend行為實現了這一點,當然,您可以根據需要使用常規的附加行為來完成此操作,但是我在這里保持簡單:

public class ListBoxScrollBehavior : Behavior<ListBox>
{
    public ListBoxScrollHandler ScrollHandler
    {
        get { return (ListBoxScrollHandler)GetValue(ScrollHandlerProperty); }
        set { SetValue(ScrollHandlerProperty, value); }
    }

    public static readonly DependencyProperty ScrollHandlerProperty =
        DependencyProperty.Register("ScrollHandler", typeof(ListBoxScrollHandler),
        typeof(ListBoxScrollBehavior), new PropertyMetadata(null, OnScrollHandlerChanged));

    protected override void OnAttached()
    {
        base.OnAttached();
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();
    }

    private static void OnScrollHandlerChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var behavior = d as ListBoxScrollBehavior;
        if (behavior == null)
            return;

        var oldHandler = e.OldValue as ListBoxScrollHandler;
        if (oldHandler != null)
            oldHandler.ScrollEvent -= behavior.ScrollTo;

        var newHandler = e.NewValue as ListBoxScrollHandler;
        if (newHandler != null)
            newHandler.ScrollEvent += behavior.ScrollTo;
    }

    public void ScrollTo(object item)
    {
        this.AssociatedObject.ScrollIntoView(item);
    }

}

因此,我們的行為包含一個“ ScrollHandler”依賴項屬性,可以將其綁定到我們的視圖模型,並通過調用列表框的ScrollIntoView方法進行響應。 之后,只需創建一個視圖模型即可,該視圖模型提供此屬性以及用於初始化列表項的代碼以及一個響應按鈕按下並調用其滾動處理程序的ScrollTo方法的命令處理程序:

public class MainViewModel : ViewModelBase
{
    private ObservableCollection<string> _MyItems = new ObservableCollection<string>();
    public ObservableCollection<string> MyItems
    {
        get { return this._MyItems; }
        set { this._MyItems = value; RaisePropertyChanged(); }
    }

    private string _SelectedItem;
    public string SelectedItem
    {
        get { return this._SelectedItem; }
        set { this._SelectedItem = value; RaisePropertyChanged(); }
    }

    public ICommand ScrollCommand { get { return new RelayCommand<string>(OnScroll); } }
    private void OnScroll(string item)
    {
        this.ScrollHandler.ScrollTo(item);
    }

    private ListBoxScrollHandler _ScrollHandler = new ListBoxScrollHandler();
    public ListBoxScrollHandler ScrollHandler
    {
        get { return this._ScrollHandler;}
        set { this._ScrollHandler = value; RaisePropertyChanged(); }
    }

    public MainViewModel()
    {
        for (int i = 0; i < 1000; i++)
            this.MyItems.Add(i.ToString());
    }
}

運行代碼,單擊按鈕,列表框將向下滾動到包含“ 500”內容的元素。 顯然,如果只需要此行為的子集(例如,滾動到當前選定的項目),則可以相應地修改此行為。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM