美文网首页
C# xaml 开发技巧

C# xaml 开发技巧

作者: Brent姜 | 来源:发表于2017-06-01 16:09 被阅读75次

    设计期见查看ViewModel内容

    问题

    Setting design time DataContext on a Window is giving a compiler error?

    I have the following XAML below for the main window in my WPF application, I am trying to set the design time d:DataContext below, which I can successfully do for all my various UserControls, but it gives me this error when I try to do it on the window...

    Error 1 The property 'DataContext' must be in the default namespace or in the element namespace 'http://schemas.microsoft.com/winfx/2006/xaml/presentation'. Line 8 Position 9. C:\dev\bplus\PMT\src\UI\MainWindow.xaml 8 9 UI

    <Window x:Class="BenchmarkPlus.PMT.UI.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:UI="clr-namespace:BenchmarkPlus.PMT.UI"
        xmlns:Controls="clr-namespace:BenchmarkPlus.PMT.UI.Controls"
        d:DataContext="{d:DesignInstance Type=UI:MainViewModel, IsDesignTimeCreatable=True}"
        Title="MainWindow" Height="1000" Width="1600" Background="#FF7A7C82">
    
        <Grid>
            <!-- Content Here -->
        </grid>
    
    </Window>
    

    解决方法

    I needed to add the mc:Ignorable="d" attribute to the Window tag. Essentially I learned something new. The d: namespace prefix that Expression Blend/Visual Studio designer acknowledges is actually ignored/"commented out" by the real compiler/xaml parser!

    <Window 
    ...
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    ...
    />
    

    The following was taken from

    Nathan, Adam (2010-06-04). WPF 4 Unleashed (Kindle Locations 1799-1811). Sams. Kindle Edition.

    Markup Compatibility

    The markup compatibility XML namespace (http://schemas.openxmlformats.org/markup-compatibility/2006, typically used with an mc prefix) contains an Ignorable attribute that instructs XAML processors to ignore all elements/attributes in specified namespaces if they can’t be resolved to their .NET types/members. (The namespace also has a ProcessContent attribute that overrides Ignorable for specific types inside the ignored namespaces.)

    Expression Blend takes advantage of this feature to do things like add design-time properties to XAML content that can be ignored at runtime.

    mc:Ignorable can be given a space-delimited list of namespaces, and mc:ProcessContent can be given a space-delimited list of elements. When XamlXmlReader encounters ignorable content that can’t be resolved, it doesn’t report any nodes for it. If the ignorable content can be resolved, it will be reported normally. So consumers don’t need to do anything special to handle markup compatibility correctly.

    C# WPF TextBox限制MaxLength

    Set MaxLength Property of the Input Area》介绍了修改EditableComboBox控件内部TextBox的MaxLength的三种方法:

    这三种方式也可以直接用于TextBox。

    StackOverflow Question 8745325》介绍了使用反射功能直接将StringLengthAttribute绑定到XAML的方法。但这种方式我无法成功实现,似乎遇到了一些问题。

    TextBox: Minimum and Maximum Character Length Validation using ASP.Net RegularExpression Validators》在ASP.NET中使用正则表达式进行输入控件字符串长度限制,这个思路也可以用于WPF。

    最后还是直接在XAML上设置MaxLength解决项目需要。

    为表格列提供自定义排序

    参考SO的问答,通过Behavior实现:
    I created a couple of attached properties which handle this issue. I hope this comes in handy for someone!

    First - a simple interface for your directionalised comparer. This extends IComparer but gives us one more property (SortDirection). Your implementation should use this to determine the correct ordering of elements (which would otherwise have been lost).

    public interface ICustomSorter : IComparer
    {
        ListSortDirection SortDirection { get; set; }
    }
    

    Next is the attached behavior - this does two things: 1) tells the grid to use custom sort logic (AllowCustomSort=true) and b) gives us the ability to set this logic at a per-column level.

    public class CustomSortBehaviour
    {
        public static readonly DependencyProperty CustomSorterProperty =
            DependencyProperty.RegisterAttached("CustomSorter", typeof(ICustomSorter), typeof(CustomSortBehavior));
    
        public static ICustomSorter GetCustomSorter(DataGridColumn gridColumn)
        {
            return (ICustomSorter)gridColumn.GetValue(CustomSorterProperty);
        }
    
        public static void SetCustomSorter(DataGridColumn gridColumn, ICustomSorter value)
        {
            gridColumn.SetValue(CustomSorterProperty, value);
        }
    
        public static readonly DependencyProperty AllowCustomSortProperty =
            DependencyProperty.RegisterAttached("AllowCustomSort", typeof(bool),
            typeof(CustomSortBehavior), new UIPropertyMetadata(false, OnAllowCustomSortChanged));
    
        public static bool GetAllowCustomSort(DataGrid grid)
        {
            return (bool)grid.GetValue(AllowCustomSortProperty);
        }
    
        public static void SetAllowCustomSort(DataGrid grid, bool value)
        {
            grid.SetValue(AllowCustomSortProperty, value);
        }
    
        private static void OnAllowCustomSortChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var existing = d as DataGrid;
            if (existing == null) return;
    
            var oldAllow = (bool)e.OldValue;
            var newAllow = (bool)e.NewValue;
    
            if (!oldAllow && newAllow)
            {
                existing.Sorting += HandleCustomSorting;
            }
            else
            {
                existing.Sorting -= HandleCustomSorting;
            }
        }
    
        private static void HandleCustomSorting(object sender, DataGridSortingEventArgs e)
        {
            var dataGrid = sender as DataGrid;
            if (dataGrid == null || !GetAllowCustomSort(dataGrid)) return;
    
            var listColView = dataGrid.ItemsSource as ListCollectionView;
            if (listColView == null)
                throw new Exception("The DataGrid's ItemsSource property must be of type, ListCollectionView");
    
            // Sanity check
            var sorter = GetCustomSorter(e.Column);
            if (sorter == null) return;
    
            // The guts.
            e.Handled = true;
    
            var direction = (e.Column.SortDirection != ListSortDirection.Ascending)
                                ? ListSortDirection.Ascending
                                : ListSortDirection.Descending;
    
            e.Column.SortDirection = sorter.SortDirection = direction;
            listColView.CustomSort = sorter;
        }
    }
    

    To use it, implement an ICustomComparer (with a parameterless constructor) and in your XAML:

    <UserControl.Resources>
        <converters:MyComparer x:Key="MyComparer"/>
        <!-- add more if you need them -->
    </UserControl.Resources>
    <DataGrid behaviours:CustomSortBehaviour.AllowCustomSort="True" ItemsSource="{Binding MyListCollectionView}">
        <DataGrid.Columns>
            <DataGridTextColumn Header="Test" Binding="{Binding MyValue}" behaviours:CustomSortBehaviour.CustomSorter="{StaticResource MyComparer}" />
        </DataGrid.Columns>
    </DataGrid>

    相关文章

      网友评论

          本文标题:C# xaml 开发技巧

          本文链接:https://www.haomeiwen.com/subject/vqsefxtx.html