ডেটা টেম্পলেট থেকে প্যারেন্ট ডেটা কনটেক্সট অ্যাক্সেস করুন


112

আমার একটি ListBoxযা ভিউমোডেলে একটি শিশু সংগ্রহের সাথে আবদ্ধ। তালিকার বাক্স আইটেমগুলি পিতামাতার ভিউমোডেলের কোনও সংস্থার উপর ভিত্তি করে একটি ডেটাপ্যাম্পলে স্টাইল করা হয়:

<Style x:Key="curveSpeedNonConstantParameterCell">
   <Style.Triggers>
      <DataTrigger Binding="{Binding Path=DataContext.CurveSpeedMustBeSpecified, 
          ElementName=someParentElementWithReferenceToRootDataContext}" 
          Value="True">
          <Setter Property="Control.Visibility" Value="Hidden"></Setter>
      </DataTrigger>
   </Style.Triggers>
</Style>

আমি নিম্নলিখিত আউটপুট ত্রুটি পেয়েছি:

System.Windows.Data Error: 39 : BindingExpression path error: 
 'CurveSpeedMustBeSpecified' property not found on 
   'object' ''BindingListCollectionView' (HashCode=20467555)'. 
 BindingExpression:Path=DataContext.CurveSpeedMustBeSpecified; 
 DataItem='Grid' (Name='nonConstantCurveParametersGrid');
 target element is 'TextBox' (Name=''); 
 target property is 'NoTarget' (type 'Object')

সুতরাং যদি আমি বাঁধাই অভিব্যক্তি পরিবর্তন করতে "Path=DataContext.CurrentItem.CurveSpeedMustBeSpecified"এটি কাজ করে, কিন্তু শুধুমাত্র যতদিন পিতা বা মাতা ব্যবহারকারী নিয়ন্ত্রণের datacontext একটি হল BindingListCollectionView। এই গ্রহণযোগ্য নয় কারণ বৈশিষ্ট্য ব্যবহারকারী নিয়ন্ত্রণ বেঁধে বাকি CurrentItemউপর BindingListস্বয়ংক্রিয়ভাবে।

আমি কীভাবে শৈলীর অভ্যন্তরে বাধ্যতামূলক এক্সপ্রেশনটি নির্দিষ্ট করতে পারি যাতে এটি পিতামাতার তথ্য প্রসঙ্গে কালেকশন ভিউ বা একক আইটেম নির্বিশেষে কাজ করে?

উত্তর:


161

সিলভারলাইটে আপেক্ষিক উত্স নিয়ে আমার সমস্যা ছিল। অনুসন্ধান এবং পড়ার পরে আমি কিছু অতিরিক্ত বাইন্ডিং লাইব্রেরি ব্যবহার না করে উপযুক্ত সমাধান খুঁজে পাইনি। তবে, এখানে এমন কোনও উপাদানকে সরাসরি উল্লেখ করে যার মাধ্যমে আপনি ডেটা প্রসঙ্গটি জানেন তা প্যারেন্ট ডেটা কনটেক্সট এ অ্যাক্সেস পাওয়ার জন্য আরেকটি পদ্ধতির উপায় এখানে । এটি আপনার ব্যবহারের পক্ষে Binding ElementNameযতক্ষণ না নিজের নামকরণের প্রতি শ্রদ্ধাবোধ করে এবং উপাদানগুলির templates/ stylesজুড়ে ভারী পুনরায় ব্যবহার না করে: এটি বেশ ভাল ব্যবহার করে এবং কার্যকর করে :

<ItemsControl x:Name="level1Lister" ItemsSource={Binding MyLevel1List}>
  <ItemsControl.ItemTemplate>
    <DataTemplate>
      <Button Content={Binding MyLevel2Property}
              Command={Binding ElementName=level1Lister,
                       Path=DataContext.MyLevel1Command}
              CommandParameter={Binding MyLevel2Property}>
      </Button>
    <DataTemplate>
  <ItemsControl.ItemTemplate>
</ItemsControl>

এই কাজ করে আপনি মধ্যে বোতাম করা Style/ Template:

<Border.Resources>
  <Style x:Key="buttonStyle" TargetType="Button">
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="Button">
          <Button Command={Binding ElementName=level1Lister,
                                   Path=DataContext.MyLevel1Command}
                  CommandParameter={Binding MyLevel2Property}>
               <ContentPresenter/>
          </Button>
        </ControlTemplate>
      </Setter.Value>
    </Setter>
  </Style>
</Border.Resources>

<ItemsControl x:Name="level1Lister" ItemsSource={Binding MyLevel1List}>
  <ItemsControl.ItemTemplate>
    <DataTemplate>
      <Button Content="{Binding MyLevel2Property}" 
              Style="{StaticResource buttonStyle}"/>
    <DataTemplate>
  <ItemsControl.ItemTemplate>
</ItemsControl>

প্রথমে আমি ভেবেছিলাম যে x:Namesপিতামাতার উপাদানগুলি কোনও শিপযুক্ত আইটেমের মধ্যে থেকে অ্যাক্সেসযোগ্য নয়, তবে যেহেতু আমি এর চেয়ে ভাল কোনও সমাধান খুঁজে পাইনি, আমি কেবল চেষ্টা করেছি এবং এটি ঠিকঠাক কাজ করে।


1
আমার প্রকল্পে আমার এই সঠিক কোডটি রয়েছে তবে এটি ভিউমোডেলগুলি ফাঁস করছে (চূড়ান্তরূপে ডাকা হয় না, কমান্ড বাইন্ডিং ডেটা কনটেক্সট ধরে রাখে বলে মনে হয়)। আপনি কি তা যাচাই করতে পারেন যে এই সমস্যাটি আপনার জন্যও রয়েছে?
জোরিস ওয়েমার

@ জুভ এই কাজ করে তবে কি এটি করা সম্ভব হয় যাতে এটি একই টেম্পলেটটি প্রয়োগকারী সমস্ত আইটেম নিয়ন্ত্রণের জন্য গুলি চালায়? নামটি অনন্য so তাই আমাদের প্রত্যেকটির জন্য আলাদা আলাদা টেম্পলেট প্রয়োজন, যদি না আমি কিছু অনুপস্থিত।
ক্রিস

1
@ জু আমার শেষ অবজ্ঞা করুন, আমি এটি সন্ধানের সাথে আত্মীয়স্বজন ব্যবহার করে এবং পূর্বসূরীর দ্বারা অনুসন্ধান করে কাজ করতে পেরেছি (সুতরাং নাম অনুসারে অনুসন্ধান না করে সমস্ত কিছু)। ItemsControls আমার ক্ষেত্রে আমি আবার বলছি ব্যবহারে প্রতিটি এক একটি টেম্পলেট বাস্তবায়নে যাতে খনি ভালো দেখায়: কমান্ড = "{বাঁধাই RelativeSource = {RelativeSource FindAncestor, AncestorType = {X: প্রকার ItemsControl}}, পাথ = DataContext.OpenDocumentBtnCommand}"
ক্রিস

48

আপনি এর RelativeSourceমতো পিতামাতার উপাদানগুলি খুঁজতে ব্যবহার করতে পারেন -

Binding="{Binding Path=DataContext.CurveSpeedMustBeSpecified, 
RelativeSource={RelativeSource AncestorType={x:Type local:YourParentElementType}}}"

আরও তথ্যের জন্য এই এসও প্রশ্নটি দেখুন RelativeSource


10
Mode=FindAncestorএটির কাজ করার জন্য আমাকে নির্দিষ্ট করে দিতে হয়েছিল, তবে এটি এমভিভিএম দৃশ্যে কাজ করে এবং অনেক বেশি ভাল কারণ এটি নামকরণ নিয়ন্ত্রণকে এড়িয়ে চলে। Binding="{Binding Path=DataContext.CurveSpeedMustBeSpecified, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:YourParentElementType}}}"
অ্যাফেক্স

1
<3 এর মত কাজ করুন এবং মোডটি নির্দিষ্ট করতে হবে না, নেট 4.6.1
ব্যবহারকারীর 2475096

30

রিলেটিভসোর্স বনাম এলিমেন্টনাম

এই দুটি পদ্ধতির একই ফলাফল অর্জন করতে পারে,

RelativeSrouce

Binding="{Binding Path=DataContext.MyBindingProperty, 
          RelativeSource={RelativeSource AncestorType={x:Type Window}}}"

এই পদ্ধতিটি ভিজ্যুয়াল ট্রিতে একটি টাইপ উইন্ডো (এই উদাহরণস্বরূপ) এর নিয়ন্ত্রণ অনুসন্ধান করে এবং যখন এটি খুঁজে পায় আপনি মূলত এটি DataContextব্যবহার করে অ্যাক্সেস করতে পারেন Path=DataContext....। এই পদ্ধতির প্রসেসগুলি হ'ল আপনাকে কোনও নামের সাথে আবদ্ধ করার দরকার নেই এবং এটি এক ধরণের গতিশীল, তবে আপনার ভিজ্যুয়াল ট্রিতে করা পরিবর্তনগুলি এই পদ্ধতিটিকে প্রভাবিত করতে পারে এবং সম্ভবত এটি ভেঙে দিতে পারে।

ElementName

Binding="{Binding Path=DataContext.MyBindingProperty, ElementName=MyMainWindow}

এই পদ্ধতিটি একটি Nameদৃic় স্থিতিশীলকে রেফার করে, যতক্ষণ না আপনার সুযোগটি এটি দেখতে পাবে, আপনি ঠিক আছেন You অবশ্যই আপনার নামকরণের কনভেনশনে এই পদ্ধতিটি অবশ্যই না ভাঙ্গা উচিত approach Name="..."আপনার উইন্ডো / ব্যবহারকারীর নিয়ন্ত্রণের জন্য একটি ।

যদিও তিনটি ধরণের ( RelativeSource, Source, ElementName) একই জিনিস করতে সক্ষম, তবে নিম্নলিখিত এমএসডিএন নিবন্ধ অনুসারে, প্রত্যেকেই তাদের নিজস্ব ক্ষেত্রের বিশেষত ব্যবহার করতে পারবেন।

কীভাবে: বাইন্ডিং উত্স নির্দিষ্ট করুন

প্রতিটি প্লাসের সংক্ষিপ্ত বিবরণ পৃষ্ঠার নীচে টেবিলের মধ্যে আরও একটি বিশদের লিঙ্কটি সন্ধান করুন।


18

ডাব্লুপিএফ-তে কীভাবে অনুরূপ কিছু করা যায় তা আমি অনুসন্ধান করছিলাম এবং আমি এই সমাধান পেয়েছি:

<ItemsControl ItemsSource="{Binding MyItems,Mode=OneWay}">
<ItemsControl.ItemsPanel>
    <ItemsPanelTemplate>
        <StackPanel Orientation="Vertical" />
    </ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
    <DataTemplate>
        <RadioButton 
            Content="{Binding}" 
            Command="{Binding Path=DataContext.CustomCommand, 
                        RelativeSource={RelativeSource Mode=FindAncestor,      
                        AncestorType={x:Type ItemsControl}} }"
            CommandParameter="{Binding}" />
    </DataTemplate>
</ItemsControl.ItemTemplate>

আমি আশা করি এটি অন্য কারও জন্য কাজ করে। আমার কাছে একটি ডেটা প্রসঙ্গ রয়েছে যা আইটেমকন্ট্রোলগুলিতে স্বয়ংক্রিয়ভাবে সেট হয়ে গেছে এবং এই ডেটা প্রসঙ্গে দুটি বৈশিষ্ট্য রয়েছে: MyItems-যাহার একটি সংগ্রহ- এবং একটি কমান্ড 'কাস্টমকম্যান্ড'। কারণItemTemplate একটি ব্যবহার করছে DataTemplate, DataContextউপরের স্তরের সরাসরি অ্যাক্সেসযোগ্য নয়। তারপরে পিতামাতার ডিসি পাওয়ার জন্য একত্রে একটি আপেক্ষিক পাথ এবং ItemsControlটাইপ অনুসারে ফিল্টার করা হয় ।


0

সমস্যাটি হ'ল কোনও ডেটাপ্যাম্পলেট এটি প্রয়োগ করা কোনও উপাদানটির অংশ নয়।

এর অর্থ আপনি যদি টেমপ্লেটের সাথে আবদ্ধ হন তবে এমন কোনও কিছুকে আবদ্ধ করছেন যার কোনও প্রসঙ্গ নেই।

তবে আপনি যদি কোনও উপাদান টেম্পলেটটির অভ্যন্তরে রাখেন তবে যখন সেই উপাদানটি পিতামাতার সাথে প্রয়োগ করা হয় এটি একটি প্রসঙ্গ এবং বাঁধাইয়ের পরে কাজ করে

সুতরাং এটি কাজ করবে না

<DataTemplate >
    <DataTemplate.Resources>
        <CollectionViewSource x:Key="projects" Source="{Binding Projects}" >

তবে এটি পুরোপুরি কাজ করে

<DataTemplate >
    <GroupBox Header="Projects">
        <GroupBox.Resources>
            <CollectionViewSource x:Key="projects" Source="{Binding Projects}" >

কারণ ডেটেটেমপ্লেট প্রয়োগ করার পরে গ্রুপবক্সটি পিতামাতার মধ্যে স্থাপন করা হয় এবং এর প্রসঙ্গে অ্যাক্সেস থাকবে

সুতরাং আপনাকে যা করতে হবে তা হ'ল টেমপ্লেট থেকে শৈলীটি সরিয়ে এটি টেমপ্লেটের একটি উপাদান হিসাবে নিয়ে যাওয়া

নোট করুন যে আইটেমসন্ট্রোলের প্রসঙ্গটি হ'ল নিয়ন্ত্রণ নয় আইটেমটি কম্বোবক্সের জন্য কম্বোবক্সআইটেম কম্বোবক্স নিজেই নয় যে ক্ষেত্রে আপনার পরিবর্তে আইটেমকন্টেইনার স্টাইল নিয়ন্ত্রণগুলি ব্যবহার করা উচিত


0

হ্যাঁ, আপনি এটি ব্যবহার করে সমাধান করতে পারেন ElementName=Something জুভের পরামর্শ অনুসারে ।

কিন্ত!

যদি কোনও শিশু উপাদান (যার উপর আপনি এই ধরণের বাঁধাই ব্যবহার করেন) এমন কোনও ব্যবহারকারী নিয়ন্ত্রণ যা আপনি প্যারেন্ট কন্ট্রোলটিতে উল্লিখিত একই উপাদানটির নাম ব্যবহার করেন, তবে বাইন্ডিংটি ভুল অবজেক্টে চলে যায় !!

আমি জানি এই পোস্টটি কোনও সমাধান নয় তবে আমি ভেবেছিলাম যে যারা বাইন্ডিংয়ের মধ্যে এলিমেন্টনাম ব্যবহার করেন তাদের প্রত্যেককে এটি জানা উচিত, কারণ এটি একটি সম্ভাব্য রানটাইম বাগ।

<UserControl x:Class="MyNiceControl"
             x:Name="TheSameName">
   the content ...
</UserControl>

<UserControl x:Class="AnotherUserControl">
        <ListView x:Name="TheSameName">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <MyNiceControl Width="{Binding DataContext.Width, ElementName=TheSameName}" />
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
</UserControl>
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.