簡體   English   中英

使用綁定到其他屬性的轉換器刷新綁定

[英]Refresh binding with converter bound to other property

我目前正在為Windows 10構建WinRT應用,但遇到了一個似乎無法找到答案的問題。

在我的主頁上,我有一個綁定到ViewModel中ObservableCollection的地圖標記的列表。 對於這些標記中的每一個,我都需要根據ViewModel的另一個屬性(我們稱之為PropertySelector)的值,顯示MapMarker類中的Property1或Property2文本。

我發現最好的解決方案是在MapMarker類中創建一個同時包含Property1和Property2的結構,將其綁定到標記的文本字段,然后使用Converter選擇要顯示的結構。

由於您無法將屬性綁定到ConverterParameter,因此我在Converter中實現了DependencyProperty,以使其可以訪問PropertySelector。 DP工作正常,轉換器中的屬性已更新,但標記從未更新。 我明白這是因為我沒有觸發任何實際告訴標記更新的事件,但是我沒有設法通過向PropertySelector設置器添加PropertyChanged(“ MarkerList”)或嘗試以編程方式刷新綁定來實現當我使用諸如GetBinding(Text).UpdateSource()之類的屬性更改屬性時,這似乎與WPF具有不同的實現。

我這樣做對嗎? 我該怎么做才能強制綁定刷新?

這是我的相關代碼:

MainPage.xaml中

<Page.Resources>
        <local:PropertySelectorConverter x:Key="propertySelectorConverter" 
                                   PropertySelector="{Binding PropertySelector}" />
</Page.Resources>

...

<Maps:MapControl>
    <Maps:MapItemsControl ItemsSource="{Binding MarkerList}">
        <Maps:MapItemsControl.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding Properties, Converter={StaticResource propertySelectorConverter}}" />
            </DataTemplate>
        </Maps:MapItemsControl.ItemTemplate>
    </Maps:MapItemsControl>
</Maps:MapControl>
<Button Text="Switch Data" Click="SwitchButton_Click" />

MainPage.xaml.cs中

public void SwitchButton_Click(object sender, EventArgs e)
{
    viewModel.PropertySelector= !viewModel.PropertySelector
}

ViewModel.cs

class ViewModel : INotifyPropertyChanged
{
    private ObservableCollection<Marker> markerList = new ObservableCollection<Marker>();
    public ObservableCollection<Marker> MarkerList
    {
        get { return markerList; }
        set { markerList = value; OnPropertyChanged("MarkerList"); }
    }

    private bool propertySelector = false;
    public bool PropertySelector
    {
        get { return propertySelector; }
        set { propertySelector = value; OnPropertyChanged("PropertySelector"); }
    }
}

Marker.cs

public class Marker
{
    public Tuple<double, double> Properties { get; set; } = Tuple.Create(10, 7);
}

Converter.cs

public class PropertySelectorConverter : DependencyObject, IValueConverter
{
    public bool PropertySelector
    {
        get { return (bool)GetValue(PropertySelectorProperty); }
        set { SetValue(PropertySelectorProperty, value); }
    }

    public static readonly DependencyProperty PropertySelectorProperty =
        DependencyProperty.Register("PropertySelector", typeof(bool), typeof(PropertySelectorConverter), new PropertyMetadata(null, CurrentItemChangedCallback));

    private static void CurrentItemChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args)
    {

    }

    public object Convert(object value, Type targetType, object parameter, string language)
    {
        var properties = (Tuple<double, double>)value;
        return PropertySelector ? properties.Item1 : properties.Item2;
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        throw new NotImplementedException();
    }
}

感謝您的時間。

缺少一個很好的, 最小的完整的代碼示例來清楚地說明您的問題,很難甚至不可能提供具體的建議。 但是有一些普遍的想法可以分享……

首先,以我的經驗, ConverterParameter對於提供給轉換器的靜態(即編譯時)信息更有用。 例如,當您編寫了一個通用轉換器時,該轉換器需要給定綁定的一些特定數據,但是該數據值在編譯時是已知的。

在您的方案中,實際上,轉換器的多個輸入值在運行時會有所不同。 對於這種情況,恕我直言,使用MultiBinding更合適。 這使您可以提供兩個或多個綁定源,如果其中任何一個源發生更改,WPF都會重新計算綁定值。 不幸的是,這是WPF功能,並且與許多非常有用的WPF功能一樣,Windows Store / Winrt API中已將其省略。

但是,您可以構造一個簡單的中間視圖模型類來實現相同的目的。 例如:

class MultiBindingViewModel : DependencyObject
{
    public static readonly DependencyProperty PropertiesProperty = DependencyProperty.Register(
        "Properties", typeof(Tuple<double, double>), typeof(MultiBindingViewModel), new PropertyMetadata(null, OnPropertyChanged);
    public static readonly DependencyProperty PropertySelectorProperty = DependencyProperty.Register(
        "PropertySelector", typeof(bool), typeof(MultiBindingViewModel), new PropertyMetadata(null, OnPropertyChanged);
    public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
        "Value", typeof(double), typeof(MultiBindingViewModel), null);

    public Tuple<double, double> Properties
    {
        get { return (Tuple<double, double>)GetValue(PropertiesProperty); }
        set { SetValue(PropertiesProperty, value); }
    }

    public bool PropertySelector
    {
        get { return (bool)GetValue(PropertySelectorProperty); }
        set { SetValue(PropertySelectorProperty, value); }
    }

    public double Value
    {
        get { return (double)GetValue(ValueProperty); }
        set { SetValue(ValueProperty, value); }
    }

    private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        MultiBindingViewModel model = (MultiBindingViewModel)d;

        model.Value = model.PropertySelector ? model.Properties.Item1 : model.Properties.Item2;
    }
}

然后在您的XAML中使用它,例如:

<TextBlock>
    <TextBlock.Text>
        <Binding Path="Value">
            <Binding.Source>
                <local:MultiBindingViewModel Properties="{Binding Properties}"
                                             PropertySelector="{Binding PropertySelector}/>
            </Binding.Source>
        </Binding>
    </TextBlock.Text>
</TextBlock>

注意:缺少完整的代碼示例,以上只是瀏覽器編寫的代碼。 可能存在語法錯誤,或者甚至可能遺漏了Windows Store所需的一些關鍵代碼。 當然,確切的綁定源,路徑和XML名稱空間可能需要進行一些調整,因為我無法確定您如何設置數據上下文等。

但希望上面的內容足夠清楚地顯示了可以在項目中使用的基本方法。


為了完整MultiBinding ,使用MultiBinding的WPF方法如下所示:

MultiBinding始終具有一個實現IMultiValueConverter的轉換器。 Convert()該接口的方法看起來像的IValueConverter ,不同之處在於代替object value參數允許一個輸入值進行轉換,它具有object[] values參數。

根據您提供的代碼,我希望您的轉換器看起來像這樣:

public class PropertySelectorConverter : IMultiValueConverter
{    
    public object Convert(object[] values, Type targetType, object parameter, string language)
    {
        var properties = (Tuple<double, double>)values[0];
        bool propertySelector = (bool)values[1];

        return propertySelector ? properties.Item1 : properties.Item2;
    }

    public object ConvertBack(object[] values, Type targetType, object parameter, string language)
    {
        throw new NotSupportedException();
    }
}

然后在您的XAML中,您將執行以下操作:

<TextBlock>
    <TextBlock.Text>
        <MultiBinding Converter="{StaticResource propertySelectorConverter}">
            <Binding Source="." Path="Properties"/>
            <Binding Source="." Path="PropertySelector"/>
        </MultiBinding>
    </TextBlock.Text>
</TextBlock>

暫無
暫無

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

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