【发布时间】:2012-03-30 15:34:48
【问题描述】:
这可能会有点长,但就是这样。我使用 MVVM 模式创建了一个小型的向导式示例应用程序(基本上是我的“真实”应用程序中代码的简化版本)。在这个应用程序中,主窗口从视图模型的 List<..> 移动,每个视图模型都显示其关联的视图。我有 2 个基本相同的视图模型类,它们显示相同的视图。
视图上有一个组合框,填充了一个浮点数组。 SelectedItem 绑定到视图模型上的浮动属性。我为组合框创建了一个模板,以将每个项目显示为一个 TextBlock,文本采用浮点值并通过值转换器。
问题是,当我在视图模型之间来回切换时,只要我切换到的每个视图模型都属于同一类,一切都可以正常工作。一旦我将当前页面更改为不同视图模型的实例,值转换器的 Convert 就会使用零长度字符串的“值”参数调用。到那时为止,Convert 只被一个浮点数调用,正如我所期望的那样。
我的问题:为什么只有在切换视图模型类的情况下才使用空字符串调用转换器?
我正在附加主窗口 XAML 和视图模型,以及为每个“页面”显示的视图/视图模型。您会注意到主窗口视图模型有一个列表,其中包含 2 个 PageViewModel 实例和 2 个 OtherViewModel 实例。我可以在前两个罚款之间来回切换,并且值转换器只被调用一个浮点值。一旦我切换到第一个 OtherViewModel 实例,转换器就会获得一个“额外”调用,其中包含一个空字符串作为值。
代码 sn-ps:
-
主窗口
<Grid.Resources> <DataTemplate DataType="{x:Type local:PageViewModel}"> <local:PageView /> </DataTemplate> <DataTemplate DataType="{x:Type local:OtherViewModel}"> <local:PageView /> </DataTemplate> </Grid.Resources> <!-- Page --> <ContentControl Margin="5,5,5,35" Height="100" IsTabStop="False" Content="{Binding CurrentPage}" /> <!-- Commands --> <Button Margin="5,115,0,0" Width="75" Content="< Back" VerticalAlignment="Top" HorizontalAlignment="Left" Command="{Binding BackCommand}" /> <Button Margin="85,115,0,0" Width="75" Content="Next >" VerticalAlignment="Top" HorizontalAlignment="Left" Command="{Binding NextCommand}" /> -
主窗口视图模型
public MainWindowViewModel() { m_pages = new List<BaseViewModel>(); m_pages.Add(new PageViewModel(1, 7f)); m_pages.Add(new PageViewModel(2, 8.5f)); m_pages.Add(new OtherViewModel(3, 10f)); m_pages.Add(new OtherViewModel(4, 11.5f)); m_currentPage = m_pages.First(); m_nextCommand = new BaseCommand(param => this.OnNext(), param => this.EnableNext()); m_backCommand = new BaseCommand(param => this.OnBack(), param => this.EnableBack()); } // Title public string Title { get { return (CurrentPage != null) ? CurrentPage.Name : Name; } } // Pages BaseViewModel m_currentPage = null; List<BaseViewModel> m_pages = null; public BaseViewModel CurrentPage { get { return m_currentPage; } set { if (value == m_currentPage) return; m_currentPage = value; OnPropertyChanged("Title"); OnPropertyChanged("CurrentPage"); } } // Back ICommand m_backCommand = null; public ICommand BackCommand { get { return m_backCommand; } } public void OnBack() { CurrentPage = m_pages[m_pages.IndexOf(CurrentPage) - 1]; } public bool EnableBack() { return CurrentPage != m_pages.First(); } // Next ICommand m_nextCommand = null; public ICommand NextCommand { get { return m_nextCommand; } } public void OnNext() { CurrentPage = m_pages[m_pages.IndexOf(CurrentPage) + 1]; } public bool EnableNext() { return CurrentPage != m_pages.Last(); } }
注意一个视图模型的 2 个实例,然后是另一个视图模型的 2 个实例。
-
页面视图
<Grid.Resources> <x:Array x:Key="DepthList" Type="sys:Single"> <sys:Single>7</sys:Single> <sys:Single>8.5</sys:Single> <sys:Single>10</sys:Single> <sys:Single>11.5</sys:Single> </x:Array> <local:MyConverter x:Key="MyConverter" /> </Grid.Resources> <TextBlock Text="Values:" Margin="5,5,0,0"> </TextBlock> <ComboBox Width="100" Height="23" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="5,25,0,0" DataContext="{Binding}" SelectedItem="{Binding Depth}" ItemsSource="{Binding Source={StaticResource DepthList}}"> <ComboBox.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding Converter={StaticResource MyConverter}}" /> </DataTemplate> </ComboBox.ItemTemplate> </ComboBox> -
PageViewModel/OtherViewModel/MyConverter
public class PageViewModel : BaseViewModel { public PageViewModel(int index, float depth) { Depth = depth; Name = "Page #" + index.ToString(); } public float Depth { get; set; } } public class OtherViewModel : BaseViewModel { public OtherViewModel(int index, float depth) { Depth = depth; Name = "Other #" + index.ToString(); } public float Depth { get; set; } } [ValueConversion(typeof(DateTime), typeof(String))] public class MyConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { Debug.WriteLine("IValueConverter.Convert : received a " + value.GetType().Name); string text = ""; if (value is float) { text = value.ToString(); } else { throw new ArgumentException("MyConverter : input value is NOT a float."); } return text; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { return float.Parse(value as string); } }
注意:我可以删除 Convert 方法中的异常,一切似乎都正常。但是,我想知道为什么会这样。为什么转换器得到一个空字符串而不是预期的浮点数,并且只有当我们切换视图模型时?
任何见解将不胜感激。提前致谢... 乔
【问题讨论】:
-
您是否尝试将 DataTemplate 上的 DataType 设置为浮动?
-
Silvermind,我刚刚尝试将 DataType="{x:Type sys:Single}" 添加到 PageView 的 DataTemplate 行,但我仍然遇到同样的问题。我仍然收到一个以空字符串作为值的转换器的调用。
标签: wpf binding mvvm ivalueconverter