gpt4 book ai didi

c# - 如何在 DataContext 略有不同的情况下重用 UserControl?

转载 作者:太空宇宙 更新时间:2023-11-03 13:32:50 25 4
gpt4 key购买 nike

这是我在 StackOverflow 上的第一篇文章,也是我的第一个问题。我使用 MVVM 模式(称为 Block)在 WPF 中创建了一个 UserControl。此 UserControl 应在另一个 UserControl 中使用,作为 ListBox(称为 Sector)的 DataTemplate。

Block Control 应该作为独立的和作为不同 UserControls 的 DataTemplate 使用。

如果我在 Block View 中设置 DataContext,独立版本效果很好,但不是扇区 View 的一部分。

如果我不在 Block 的 View 中设置 DataContext,它会在 Sector 中工作,但不会独立运行。

我的问题是,是否只有将 DataContext 保留在 Block 的 View 中并将其设置在我使用 Control 或 ViewModel 的 View 中?

这是我的代码:

block 模型:

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
}

block 的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

区 block View :

<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()
{
}
}

扇区ViewModel:

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();
}
}

扇区 View :

<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:希望我的英文没我想的那么差

最佳答案

这是 WPF 新用户的常见问题。您有两种可能的解决方案。使用 MVVM 时,您不需要在任何地方设置 UserControlDataContext。相反,您只需将 DataTemplate 添加到您的 App.xaml 即可进行配对:

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

这样,每当您显示 BlockViewModel 的实例时,框架都会显示相关的 BlockView(就像您在 SectorView< 中所做的那样)/类)。

另一种选择是将 MVVM 用于 UserControl(改为使用 Bindable DependencyProperty), 在内部设置其 DataContext 并在内部元素上使用 RelativeSource 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 的任何对象。

关于c# - 如何在 DataContext 略有不同的情况下重用 UserControl?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19900529/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com