在运行时转换值

时间:2016-02-24 16:44:58

标签: c# wpf converter unity-container prism

我有一个小问题,但根本无法弄清楚如何处理它的正确的方式。

我有两个简单的模型:

public class Employee
{
    public string Name { get; set; }
    public string Surname { get; set; }
    public DateTime DateOfBirth { get; set; }

    public Address EmployeeAddress { get; set; }

    //hierachy level
    public int EmployeeLevelID { get; set; }
}

和另一个模型:

public class EmployeeLevel
{
    public string DisplayName { get; set; }
    public int LevelID { get; set; }
}

EmployeeLevel我的意思是LevelID 1 DisplayName 经理LevelID 2将是例如普通员工

如您所见,我正在存储int的{​​{1}}值,该值确定当前EmployeeLevelID是谁。这就是为什么用户可以自己确定他们的位置Employee是什么,这就是他们在两种不同模型中分开的原因。

我需要做的是,在页面/表单上显示当前员工的信息时,我想显示他的职位DisplayNames,而不是DisplayName

问题是,带有ID的所有职位列表都存储在我的LevelID下(我在我的项目中使用EmployeeRepository& Unity),即使我建立一个Prism,我将无法轻松传递该集合。

我当然可以创建一个单独的图层,它可以作为公共值的持有者(所有类都可以看到),但我不相信这是可行的方法。

任何建议(甚至关于我的模特)都会受到赞赏,因为我现在很困惑。

3 个答案:

答案 0 :(得分:1)

对于这种情况,成员类不是一个很好的数据结构,因为您不希望在每个员工中存储显示名称,这是浪费空间,如果您必须更改显示名称,则必须迭代通过具有该级别ID的所有员工。

我们可以简单地使用一个字符串数组,ID就是索引而显示名称就是值,我们甚至可以使这个数组成为类的静态成员,这样它就可以很容易地被任何物品。

org-mode

您可以使用ID作为索引来访问列表。

(defun my-org-mode-config-fn ()
  (setq require-final-newline nil))

(add-hook 'org-mode-hook 'my-org-mode-config-fn)

现在您可以通过修改静态数组中的值来更改显示名称。

public class Employee
{
static int[] DisplayNameList = new int[] { "Manager", "Regular Employee", "Intern" };

// rest of the member variables

public int EmployeeLevelID { get; set; }
}

答案 1 :(得分:1)

为什么不创建单独的视图模型,并将字符串存储在那里而不是int。然后,您所要做的就是将基础模型映射到视图模型,并将视图模型传递给视图。

public class EmployeeViewModel {
    public string Name { get; set; }
    public string Surname { get; set; }
    public DateTime DateOfBirth { get; set; }
    public Address EmployeeAddress { get; set; }
    public String EmployeeLevel { get; set; }
}

然后:

var employeeViewModel = new EmployeeViewModel {
    Name = employee.Name,
    Surname = emplployee.Surname,
    DateOfBirth = employee.DateOfBirth,
    EmployeeAddress = employee.EmployeeAddress,
    EmployeeLevel = employeeLevels
                      .First(l => l.LevelId == employee.EmployeeLevelId)
                      .Select(l => l.DisplayName)
}

当然,您可以使用AutoMapper之类的东西来简化流程。

答案 2 :(得分:0)

以下是我决定如何解决问题的方法(我仍然对任何建议持开放态度。)

在我的ViewModel下,我在构造函数中加载EmployeeLevels并将其设置为public

    public ObservableCollection<EmployeeLevel> EmployeeLevels { get; set; }

之后,我创建了IMultiValueConverter,如下所示:

public class PositionLevelConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        if (values == null || values == System.Windows.DependencyProperty.UnsetValue || values.Length != 2)
            return string.Empty;


        var collection = values[1] as ObservableCollection<EmployeeLevel>;

        if (collection == null)
            return string.Empty;

        return collection.FirstOrDefault(n => n.LevelID == (int)values[0])?.DisplayName;

    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

最后,在我的View下,我的项目看起来像这样(这是一个DataGrid控件,以类似于表的格式显示项目):

            <telerik:GridViewDataColumn Header="Position">
                <telerik:GridViewDataColumn.CellTemplate>
                    <DataTemplate>
                        <TextBlock>
                            <TextBlock.Text>
                                <MultiBinding Converter="{StaticResource PositionConverter}">
                                    <Binding Path="EmployeeLevelID"/>
                                    <Binding RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType=UserControl}" Path="DataContext.EmployeeLevels"/>
                                </MultiBinding>
                            </TextBlock.Text>
                        </TextBlock>
                    </DataTemplate>
                </telerik:GridViewDataColumn.CellTemplate>
            </telerik:GridViewDataColumn>