c# - MVVM的良好做法是在转换器中初始化StackPanel并使用ContentPresenter呈现吗?

标签 c# wpf mvvm ivalueconverter

所以这是我上次在这里提问时提出的某种跟进问题How to Vertically “center” align the multi line text

在最后一次来自答复者的评论:

Exactly that, plus that you should not manipulate UI elements in code, but instead make yourself familiar with MVVM



回答者还使用EllipseGeometryPath很好地回答了问题。但是,由于我对Path不太熟悉,所以我试图找到另一种更“适合”我的风格的方式。

我发现这是另一种实现方式:

转换器类
public class NoteOctaveConverter : IValueConverter
{
    private const double _dotDiameter = 3;
    private readonly Thickness _dotMargin = new Thickness(0.25);
    private SolidColorBrush _dotFill;
    private readonly HorizontalAlignment _dotHzAlign = HorizontalAlignment.Center;

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        int octave = (int)value;
        List<Ellipse> dots = new List<Ellipse>();
        StackPanel stack = new StackPanel();

        if ((octave > 0 && parameter as string == "TOP") || (octave < 0 && parameter as string == "BOT"))
        {
            _dotFill = Brushes.Black;
        }
        else
        {
            _dotFill = Brushes.Transparent;
        }

        for (int i = 0; i < Math.Abs(octave); i++)
        {
            dots.Add(new Ellipse());
            dots[i].Width = _dotDiameter;
            dots[i].Height = _dotDiameter;
            dots[i].Margin = _dotMargin;
            dots[i].Fill = _dotFill;
            dots[i].HorizontalAlignment = _dotHzAlign;

            stack.Children.Add(dots[i]);
        }

        return stack;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotSupportedException();
    }
}

,这就是我将其呈现给 View 的方式:
 <ContentPresenter Grid.Column="1" Grid.Row="2"
                      Content="{Binding Path=MusicalNotation.Octave, Converter={StaticResource NoteOctaveConverter}, ConverterParameter=BOT, Mode=OneWay}"
                      HorizontalAlignment="Center" VerticalAlignment="Top"/>

如果答案是“不操作代码中的UI元素”是什么意思(我是MVVM的新手),则为idk,但是从MVVM的角度来说,这种方式*可接受的,因为我想尝试在良好的环境中使用MVVM道路?

*)这种方式=使用StackPanelConverter中显示一个ContentPresenter

附加说明:

我之所以使用ContentPresenter而不是Path的原因是,我需要很好地理解自己的工作,因为我可能必须在演示 session 中将其呈现给我的讲师(我不想呈现新的(风险) IF 我有另一种可能的方法,对我来说更舒适)。

如果事实证明以我的方式使用StackPanel是不好的做法,请告诉我原因是什么。

谢谢你。

最佳答案

我建议您在内容演示者内容上使用DataTemplate

<ContentPresenter Content="{Binding X}"/>
  <COntentPresenter.ContentTemplate>
    <DataTemplate >
       <StackPanel>...</StackPanel>
    </DataTemplate>
  </COntentPresenter.ContentTemplate>
</ContentPresenter/>

显然,您需要在StackPanel内部进行一些动态收集处理-若要完成此操作,您可以阅读Bind Collection to StackPanel。这样的问题已经回答。

关于“从dataConverter返回控件是一种好习惯”:

我怀疑。因为转换器并非旨在返回完整的控件,所以这是数据模板的任务。好吧,它们显然可以但通常用于更简单的任务-一些其他格式或颜色值。当他们创建控件时,他们违反了MVVM和“XAML中的最大UI”原则。在这种情况下,他们这样做毫无优势。更糟糕的是,您很难理解转换方法,而无法获得清晰的XAML和viewmodel逻辑。

关于c# - MVVM的良好做法是在转换器中初始化StackPanel并使用ContentPresenter呈现吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24331312/

相关文章:

c# - .Net 中的自定义安装程序显示安装程序后面的表单

c# - 如何使用 C# 取消散列?

wpf - ViewModel操纵View的最佳方法是什么?

jquery - jquery、Knockoutjs、backbone.js 之间的关系/差异是什么?

c# - 单击 CancelBtn 取消更改

c# - Roslyn 编译器服务器报告与构建任务不同的哈希版本

c# - 是否可以运行托管在 Windows 服务中的 Orleans

wpf - WPF自定义路由事件-如何退订?

wpf - 如何在 DataGrid.DataGridTemplateColumn 内设置 UserControl 的 DataContext?

c# - 处理绑定(bind) MVVM 属性中未捕获的异常