2

これは、StackOverflow に関する私の最初の投稿であり、最初の質問でもあります。MVVMパターン(ブロックと呼ばれる)を使用してWPFでUserControlを作成しました。この UserControl は、別の UserControl で、ListBox (Sector と呼ばれる) の DataTemplate として使用する必要があります。

ブロック コントロールは、スタンドアロンとして、および異なる UserControls の DataTemplate として使用する必要があります。

ブロックのビューに DataContext を設定すると、スタンドアロン バージョンはうまく機能しますが、セクター ビューの一部としては機能しません。

ブロックのビューで DataContext を設定しないと、セクターでは機能しますが、スタンドアロンでは機能しません。

私の質問は、ブロックのビューに DataContext を残して、コントロールまたはビューモデルを使用したビューに設定する唯一の方法ですか?

ここに私のコードがあります:

ブロックのモデル:

public class BlockModel : ModelBase
{
    #region private Variables

    string blockName = "Block";
    string blockContent = "00000";

    #endregion private Variables

    #region Properties

    public string BlockName
    {
        get { return blockName; }
        set { blockName = value; NotifyPropertyChange("BlockName "); }
    }

    public string BlockContent
    {
        get { return blockContent; }
        set { blockContent = value; NotifyPropertyChange("BlockContent"); }
    }

    #endregion Properties

    #region ctor

    public BlockModel () { }

    #endregion ctor
}

ブロックのViewModel:

public class BlockViewModel : ViewModelBase
{
    #region private Variables

    string charToFill = "0";
    DelegateCommand fillWithChar;
    BlockModel dataModel = new BlockModel();

    #endregion private Variables

    #region Properties

    public Models. BlockModel DataModel
    {
        get { return dataModel; }
        set { dataModel = value; }
    }

    public string BlockContent
    {
        get { return dataModel. BlockContent; }
        set
        {
            if (dataModel. BlockContent != value)
            {
                dataModel. BlockContent = value;
                NotifyPropertyChange ("BlockContent");
            }
        }
    }

    public string BlockName
    {
        get { return dataModel. BlockName; }
        set
        {
            if (dataModel. BlockName != value)
            {
                dataModel. BlockName = value;
                NotifyPropertyChange("BlockName");
            }
        }
    }


    public string CharToFill
    {
        get { return charToFill; }
        set
        {
            if (charToFill != value)
            {
                charToFill = value;
                NotifyPropertyChange ("CharToFill");
            }
        }
    }


    public ICommand FillWithChar
    {
        get
        {
            if (fillWithChar == null)
                fillWithChar = new DelegateCommand(FillText);
            return fillWithChar;
        }
    }

    #endregion Properties

    #region ctor

    public BlockViewModel()
    {

    }

    #endregion ctor

    #region Methods

    private void FillText()
    {
        CodingBlockContent = CodingBlockContent.PadLeft(32, charToFill[0]);
    }

    #endregion Methods

}

ブロックのビュー:

<UserControl x:Class="…./Block"
         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:local="clr-namespace:…/Controls"
         mc:Ignorable="d" d:DesignWidth="460" d:DesignHeight="44">
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="124" />
        <ColumnDefinition Width="301" />
        <ColumnDefinition Width="30"/>
        <ColumnDefinition/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="30"></RowDefinition>

    </Grid.RowDefinitions>
    <TextBlock Grid.Row="0" Grid.Column="0" Text="{Binding BlockName}" 
               HorizontalAlignment="Left" VerticalAlignment="Center" FontSize="14" Margin="2,6"/>
    <ComboBox FontFamily="Consolas" Grid.Row="00" Grid.Column="1" 
              Text="{Binding BlockContent, Mode=TwoWay}" 
              Tag="{Binding BlockName}" Name="cbxBlock" FontSize="14" 
              HorizontalAlignment="Left" VerticalAlignment="Center" Width="290" Margin="1,4,0,5" IsEditable="True" Height="26">
        <ComboBoxItem Content=""></ComboBoxItem>
        <ComboBoxItem Content="0000000000000"></ComboBoxItem>
        <StackPanel HorizontalAlignment="Left" VerticalAlignment="Top" Orientation="Horizontal">
            <TextBox Margin="10,2,0,2" Text="0" Width="24" FontSize="14" Name="tbxChar" MaxLength="1"></TextBox>
            <TextBlock Margin="10,2,0,2" Text="auffüllen" VerticalAlignment="Center" FontSize="14"></TextBlock>
            <Button Margin="10,2,0,2" Content="Ausführen" Width="100"  Command="{Binding FillWithChar}"></Button>
        </StackPanel>
    </ComboBox>
    <TextBlock Grid.Row="0" Width="30" Grid.Column="2" Text="{Binding CodingBlockContent.Length}" 
               HorizontalAlignment="Left" VerticalAlignment="Center" FontSize="14" Margin="2,6,0,6" Grid.ColumnSpan="2"/>
</Grid>

セクターのモデル:

public class SectorModel
{
    #region private Variables

    int blockAmount = 4;
    string sectorNumber = "Sektor";
    int blockBegin = 0;
    bool isSectorInUse = false;

    #endregion private Variables

    #region Properties

    public string SectorNumber
    {
        get { return sectorNumber; }
        set { sectorNumber = value;}
    }

    public int BlockBegin
    {
        get { return blockBegin; }
        set
        {
            blockBegin = value;
        }
    }

    public bool IsSectorInUse
    {
        get { return isSectorInUse; }
        set { isSectorInUse = value;}
    }

    public int BlockAmount
    {
        get { return blockAmount; }
        set
        {
            blockAmount = value;;
        }
    }

    #endregion Properties

  public SectorModel()
    {
    }
}

セクターのビューモデル:

public class SectorViewModel : ViewModelBase
{
    #region private Variables

    SectorModel dataModel = new SectorModel();
    ObservableCollection<BlockViewModel> sectorBlocks = new ObservableCollection<BlockViewModel>();

    #endregion private Variables

    #region Properties

    public SectorModel DataModel
    {
        get { return dataModel; }
        set { dataModel = value; }
    }

    public ObservableCollection<BlockViewModel> SectorBlocks
    {
        get { return sectorBlocks; }
        set { sectorBlocks = value; NotifyPropertyChange ("SectorBlocks"); }
    }

    public string SectorNumber
    {
        get { return "Sektor " + DataModel.SectorNumber; }
        set { DataModel.SectorNumber = value; NotifyPropertyChange ("SectorNumber"); }
    }

    public int BlockBegin
    {
        get { return DataModel.BlockBegin; }
        set
        {
            DataModel.BlockBegin = value;
            SetBlocks();
            OnPropertyChanged("BlockBegin");
        }
    }

    public bool IsSectorInUse
    {
        get { return DataModel.IsSectorInUse; }
        set { DataModel.IsSectorInUse = value; NotifyPropertyChange ("IsSectorInUse"); }
    }

    public int BlockAmount
    {
        get { return DataModel.BlockAmount; }
        set
        {
            DataModel.BlockAmount = value;
            SetBlocks();
            NotifyPropertyChange ("CodingBlockAmount");
        }
    }

    #endregion Properties

    void SetBlocks()
    {
        while (SectorBlocks.Count != BlockAmount)
        {
            SectorBlocks.Add(new BlockViewModel());
        }

        int begin = BlockBegin;

        foreach (BlockViewModel block in SectorBlocks)
        {
            block.CodingBlockName = "Block " + begin.ToString().PadLeft(2, '0');
            block++;
        }
    }

    public SectorViewModel() 
    {
        SetBlocks();
    }
}

セクターのビュー:

<UserControl xmlns:Views="clr-namespace:…/RFIDControls"  x:Class="…/Sector"
        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" 
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="473">
<Border BorderBrush="Black" BorderThickness="0,0,0,1">
    <Expander Name="expMain" Margin="0,0,4,0">
        <Expander.Header>
            <Grid Name="grdHeader">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="100" />
                    <ColumnDefinition Width="300" />
                    <ColumnDefinition Width="30" />
                </Grid.ColumnDefinitions>
                <TextBlock Grid.Column="0" Grid.Row="0" Height="24" Text="{Binding SectorNumber}" HorizontalAlignment="Left" VerticalAlignment="Center" FontSize="14" FontWeight="Bold" Panel.ZIndex="98"/>
                <CheckBox Grid.Column="2" VerticalAlignment="Center" IsChecked="{Binding IsSectorInUse}"></CheckBox>
            </Grid>
        </Expander.Header>
        <Grid>
            <ListBox ItemsSource="{Binding SectorBlocks}" Name="listBox">
                <ListBox.ItemTemplate>
                    <DataTemplate DataType="{x:Type Views:BlockViewModel}">
                        <Views:Block/>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
        </Grid>
    </Expander>
</Border>

ありがとうございました。

ドイツからよろしく

ドミニク

PS: 私の英語が思ったほど悪くないことを願っています

4

2 に答える 2

1

これは、WPF の新規ユーザーにとって一般的な問題です。考えられる解決策は 2 つあります。DataContextMVVM を使用する場合、UserControlどこでもを設定する必要はありません。代わりに、単に a を追加してペアリングを作成できDataTemplateますApp.xaml

<DataTemplate DataType="{x:Type ViewModels:BlockViewModel}">
    <Views:BlockView />
</DataTemplate>

このようにして、 のインスタンスを表示するたびに、フレームワークは代わりBlockViewModelに関連するものを表示します (クラスで行ったように)。BlockViewSectorView

別のオプションは、MVVM を使用せUserControl(Bindable DependencyProperty代わりに s を使用)、内部で設定せ、代わりに内部の要素で s を使用することです。DataContextRelativeSource Binding

<TextBlock Grid.Row="0" Grid.Column="0" Text="{Binding DataContext.BlockName, 
    RelativeSource={RelativeSource AncestorType={
    x:Type YourXmlNamespacePrefix:BlockView}}}" HorizontalAlignment="Left" 
    VerticalAlignment="Center" FontSize="14" Margin="2,6"/>

このメソッドを使用すると、 は現在として設定されているRelativeSource Bindingオブジェクトを調べます。DataContext

于 2013-11-11T09:37:01.323 に答える
0

ブロックがコントロールとして機能するように聞こえますが、これは他のユーザーコントロールまたはテンプレートの一部に参加しているようです。私の意見では、mvvm はここでは機能しません。代わりに Dependency プロパティを使用する必要があります。私の下手な英語を許してください。

于 2013-11-11T09:12:14.810 に答える