簡體   English   中英

使用MVVM跨多個子控件的WPF UserControl自定義粘貼命令

[英]WPF UserControl custom paste command across multiple child controls with MVVM

考慮以下UserControl:

<UserControl ...>
    <UserControl.Resources>
        <inf:DecimalToPercentageConverter x:Key="DecimalToPercentageConverter"/>
    </UserControl.Resources>
    <Expander Margin="0,5,5,5" Style="{DynamicResource ExpanderStyle}" IsExpanded="True" IsTabStop="False">
        <Expander.Header>
            <TextBlock FontSize="15" Foreground="White" Text="{x:Static resources:Strings.GeneralOptions}"/>
        </Expander.Header>

        <ItemsControl ItemsSource="{Binding DaysViewSource}" IsTabStop="False" Name="ItemsControl">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <WrapPanel />
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Border Background="White" Padding="5" BorderThickness="2">
                        <HeaderedContentControl IsTabStop="False" Width="240">
                            <HeaderedContentControl.Header>
                                <StackPanel Orientation="Horizontal">
                                    <TextBlock Text="{Binding Date, StringFormat=d}" FontSize="14" Margin="3"/>
                                    <TextBlock Text="{Binding Date, StringFormat=(ddd)}" FontSize="14" Margin="3"/>
                                </StackPanel>
                            </HeaderedContentControl.Header>
                            <Grid>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="Auto" />
                                    <ColumnDefinition Width="*" />
                                </Grid.ColumnDefinitions>
                                <Grid.RowDefinitions>
                                    <RowDefinition/>
                                    <RowDefinition/>
                                    <RowDefinition/>
                                </Grid.RowDefinitions>

                                <StackPanel Orientation="Horizontal" Grid.ColumnSpan="2">
                                    <Image Margin="3" Width="16" Height="16" Source="{DynamicResource InformationIcon}" />
                                    <TextBlock Margin="1,3,3,3" Text="{Binding HoursPerAgentText}"/>
                                </StackPanel>

                                <TextBlock Grid.Row="1" Text="{x:Static resources:Strings.Utilization}" Margin="3" VerticalAlignment="Center"/>
                                <TextBox Grid.Row="1" Grid.Column="1" 
                                         Text="{Binding Utilization, ValidatesOnDataErrors=true, StringFormat='P2', Converter={StaticResource DecimalToPercentageConverter}}" 
                                         Margin="3" VerticalAlignment="Center" />

                                <TextBlock Grid.Row="2"  Text="{x:Static resources:Strings.Shrinkage}"  Margin="3" VerticalAlignment="Center"/>
                                <TextBox Grid.Row="2" Grid.Column="1" 
                                         Text="{Binding Shrinkage, ValidatesOnDataErrors=true, StringFormat='P2', Converter={StaticResource DecimalToPercentageConverter}}"  
                                         Margin="3" VerticalAlignment="Center"/>
                            </Grid>
                        </HeaderedContentControl>
                    </Border>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </Expander>
</UserControl>

它呈現如下:

UserControl呈現

我的任務是在所有日期和兩個字段中實施粘貼功能。 用戶將從Excel工作表中復制值,然后直接粘貼到其中一個文本框中。 我沒有解析邏輯,但是我對如何處理所有控件的粘貼感到困惑。

到目前為止,我嘗試了將CommandBinding與Paste命令一起使用,但這似乎僅在后面的視圖代碼中給我一個事件,理想情況下,我希望能夠處理視圖模型中的邏輯。 我知道有一些模式可以將命令綁定鏈接到具有附加屬性的視圖模型( http://codingcontext.wordpress.com/2008/12/10/commandbindings-in-mvvm/ ),在這種情況下,我在viewmodel中得到了事件,但是我得到的只是作為文本框元素的發送者(我不希望在viewmodel中得到)。

有沒有人遇到過同樣的問題,或者對如何優雅地解決這個問題有想法?

我有一個Utility項目,其中包含許多Manager類,其中一個是ClipboardManager 我的所有Manager類都遵循Singleton模式(這意味着每個類只能有一個),並且可以從BaseViewModel類中獲得。 它們都是接口的,因此我可以出於測試目的實現模擬管理器,但這是另一回事了。

ClipboardManager有一些標准方法,但是本質上針對特定任務,我需要添加以下方法:

/// <summary>
/// Copies the SecurityPermissions object specified by the securityPermissions input parameter into the computer clipboard in the SecurityPermissions format.
/// </summary>
/// <param name="securityPermissions">The SecurityPermissions object to copy into the computer clipboard.</param>
public void SetClipboardSecurityPermissions(SecurityPermissions securityPermissions)
{
    try { SetClipboardSecurityPermissionsData(securityPermissions); }
    catch (COMException)
    {
        Thread.Sleep(0);
        try { SetClipboardSecurityPermissionsData(securityPermissions); }
        catch (COMException)
        {
            MessageBox.Show("The clipboard was inaccessible, please try again later");
        }
    }
}

private void SetClipboardSecurityPermissionsData(SecurityPermissions userSecurityPermissions)
{
    List<SecurityPermission> securityPermissions = new List<SecurityPermission>(userSecurityPermissions);
    List<SerializableSecurityPermission> serializableSecurityPermissions = new List<SerializableSecurityPermission>();
    foreach (SecurityPermission securityPermission in securityPermissions) serializableSecurityPermissions.Add(new SerializableSecurityPermission(securityPermission));
    DataObject securityPermissionsDataObject = new DataObject();
    securityPermissionsDataObject.SetData("SecurityPermissions", serializableSecurityPermissions, false);
    Clipboard.SetDataObject(securityPermissionsDataObject);
}

/// <summary>
/// Retrieves a SecurityPermissions object from the computer clipboard if any data exists in the SecurityPermissions format.
/// </summary>
public SecurityPermissions GetClipboardSecurityPermissions()
{
    if (HasClipboardGotDataFormat("SecurityPermissions"))
    {
        try { return PasteClipboardSecurityPermissions(); }
        catch (COMException)
        {
            Thread.Sleep(0);
            try { return PasteClipboardSecurityPermissions(); }
            catch (COMException)
            {
                MessageBox.Show("The clipboard was inaccessible, please try again later");
            }
        }
    }
    return new SecurityPermissions();
}

private SecurityPermissions PasteClipboardSecurityPermissions()
{
    object data = Clipboard.GetData("SecurityPermissions");
    if (data != null)
    {
        List<SecurityPermission> securityPermissions = new List<SecurityPermission>();
        List<SerializableSecurityPermission> serializableSecurityPermissions = (List<SerializableSecurityPermission>)data;
        foreach(SerializableSecurityPermission serializableSecurityPermission in serializableSecurityPermissions) securityPermissions.Add(new SecurityPermission(serializableSecurityPermission));
        return new SecurityPermissions(securityPermissions);
    }
    return new SecurityPermissions();
}

這使用一種標准方法:

/// <summary>
/// Returns true if any data currently exists in the computer clipboard in the data format specified by the dataFormat input parameter.
/// </summary>
public bool HasClipboardGotDataFormat(string dataFormat)
{
    return Clipboard.ContainsData(dataFormat);
}

公共方法是有接口的方法,因此我可以從我的視圖模型訪問這些方法。 因此,這是從視圖模型處理剪貼板活動的一種方法。 現在,一旦將數據放入視圖模型中,如何在各個控件之間分配數據就將很大程度上取決於您如何設置它們。

如果您有一個通用的父視圖模型,那么我將在其中執行剪貼板活動,然后將數據分發到子控件應該很容易。

更新>>>

一種簡單的處理方法是在用戶界面中提供“粘貼” Button 您可以在父視圖模型中將其連接到某種ICommand ...我使用自定義ActionCommand (類似於RelayCommand ):

/// <summary>
/// Pastes the SecurityPermissions collection from the computer clipboard to the currently selected User.
/// </summary>
public ICommand PasteUserSecurityPermissions
{
    get { return new ActionCommand(action => ((SecurityViewModel)ViewModel).
PasteSecurityPermissions(ClipboardManager.GetClipboardSecurityPermissions()), 
canExecute => ClipboardManager.HasClipboardGotDataFormat("SecurityPermissions")); }
}

然后在子視圖模型中:

/// <summary>
/// Pastes the SecurityPermissions collection from the computer clipboard to the currently selected User object.
/// </summary>
public void PasteSecurityPermissions(SecurityPermissions securityPermissions)
{
    // Do whatever you like with the pasted data here
}

在您的情況下,您可以在每個子視圖模型中使用這些粘貼方法中的一種……非常簡單。 :)

暫無
暫無

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

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