বাইন্ডিং অবজেক্টস কোড-বর্ধিত সংজ্ঞায়িত


87

আমার কিছু অবজেক্ট রয়েছে যা পিছনে কোডে ইনস্ট্যান্ট করা আছে, উদাহরণস্বরূপ, এক্সএএমএলকে উইন্ডো.এক্স্যামেল এবং উইন্ডো.এক্সামল সিএস এর মধ্যে বলা হয় within

protected Dictionary<string, myClass> myDictionary;

আমি কীভাবে এই বিষয়টিকে কেবল এক্সএএমএল মার্কআপগুলি ব্যবহার করে উদাহরণস্বরূপ একটি তালিকার সাথে আবদ্ধ করতে পারি?

হালনাগাদ:

(আমার পরীক্ষার কোডটিতে এটি হ'ল):

<Window x:Class="QuizBee.Host.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="{Binding windowname}" Height="300" Width="300"
    DataContext="{Binding RelativeSource={RelativeSource Self}}">
    <Grid>
    </Grid>
</Window>

এবং কোডবিহাইডে

public partial class Window1 : Window
{
    public const string windowname = "ABCDEFG";

    public Window1()
    {
        InitializeComponent();
    }
}

মনে করুন শিরোনামটি ঠিক "ABCDEFG" হয়ে উঠতে হবে? তবে এটি কিছুই না দেখিয়ে শেষ হয়।


4
আশ্চর্যের বিষয় যথেষ্ট, যদি আমি উইন্ডোটির সম্পত্তি নির্ধারনের ক্রমটি পরিবর্তন করি তবে এটি কাজ করে না। যদি আমি "ডেটা কনটেক্সট" সম্পত্তি অনুসরণ করে "শিরোনাম" সম্পত্তি সেট করি তবে বাধ্যবাধকতা ঘটবে না। কেউ কি এই ব্যাখ্যা করতে পারেন? <উইন্ডো x: class = "INotifyPropertyTest.MainWindow" xmlns = " schemas.microsoft.com/winfx/2006/xaml/presentation " xmlns: X = " schemas.microsoft.com/winfx/2006/xaml " xmlns: স্থানীয় = " CLR-নামস্থান: INotifyPropertyTest "height =" 350 "width =" 525 "DataContext =" {বাঁধাই RelativeSource = {RelativeSource স্ব}} "title =" {বাঁধাই WindowName} ">
রমেশ

উত্তর:


109

আপনি আপনার নিয়ন্ত্রণ, ফর্ম ইত্যাদির জন্য ডেটা কনটেক্সট সেট করতে পারেন:

DataContext="{Binding RelativeSource={RelativeSource Self}}"

স্পষ্টতা :

উপরের মানটিতে ডেটা প্রসঙ্গ সেট করা হচ্ছে কোডের পিছনে যে কোনও উপাদান "মালিকানাধীন" হওয়া উচিত - তাই উইন্ডোর জন্য আপনার এটি উইন্ডো ঘোষণায় সেট করা উচিত।

আমি আপনার কোডটি এই কোডটি সহ কাজ করছি:

<Window x:Class="MyClass"
  Title="{Binding windowname}"
  DataContext="{Binding RelativeSource={RelativeSource Self}}"
  Height="470" Width="626">

এরপরে এই স্তরে সেট করা ডেটা কনটেক্সটটি উইন্ডোতে যে কোনও উপাদান দ্বারা উত্তরাধিকার সূত্রে প্রাপ্ত হয় (যদি না আপনি স্পষ্টভাবে এটি কোনও শিশু উপাদানের জন্য পরিবর্তন করেন), সুতরাং উইন্ডোর জন্য ডেটা কনটেক্সট সেট করার পরে আপনি কোনও নিয়ন্ত্রণ থেকে কোডবিহিন বৈশিষ্ট্যগুলিতে সরাসরি বাঁধাই করতে সক্ষম হবেন উইন্ডোতে।


4
এখানে "সেল্ফ" মানে পুরো উইন্ডো ক্লাসের চেয়ে নিয়ন্ত্রণ, তাই না?
xandy

অদ্ভুত পরিমাণে, আমার কাছে থাকা কোডটি নিম্নলিখিত এবং এটি প্রত্যাশার মতো কাজ করে না: পাবলিক আংশিক বর্গ উইন্ডো 1: উইন্ডো {পাবলিক কনস্ট স্ট্রিং উইন্ডোনেম = "এবিসিডিইএফজি"; সর্বজনীন উইন্ডো 1 () {ইনিশিয়াল কম্পোনেন্ট (); }} <উইন্ডো এক্স: ক্লাস = "কুইজবি.হোস্ট.উইনডো 1" এক্সএমএলএনস = " স্কিমাস.মাইক্রোসফট / উইনফেক্স / ২০০6 / এক্সএএমএল / প্রেফিটেশন " এক্সএমএলএনএস: x = " স্কিমাস.মাইক্রোসফট / উইনফেক্স / ২০০6/xaml " শিরোনাম = "Inding বাঁধাই উইন্ডোনেম}" উচ্চতা = "300" প্রস্থ = "300" ডেটা কনটেক্সট = "inding বাইন্ডিং রিলেটিভসোর্স = {রিলেটিভসোর্স স্ব}}"> </ উইন্ডো>
xandy

10
ওহ, এটি এখন ঠিক আছে, আমি খাঁটি পাবলিক ভেরিয়েবলের পরিবর্তে উইন্ডোয়ামটি সম্পত্তি হিসাবে পরিবর্তন করেছিলাম এবং এটি এখন প্রদর্শিত হতে পারে! ধন্যবাদ!
xandy

4
কেন এটি কেবল ডিফল্টরূপে সেট করা হয় তা আমি ভাবতে পারি না।
Okonomiyaki3000

122

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

উইন্ডো 1.xaml

<Window x:Class="QuizBee.Host.Window1"
        x:Name="Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <ListView ItemsSource="{Binding ElementName=Window1, Path=myDictionary}" />
</Window>

উইন্ডো 1.xaml.cs

public partial class Window1:Window
{
    // the property must be public, and it must have a getter & setter
    public Dictionary<string, myClass> myDictionary { get; set; }

    public Window1()
    {
        // define the dictionary items in the constructor
        // do the defining BEFORE the InitializeComponent();

        myDictionary = new Dictionary<string, myClass>()
        {
            {"item 1", new myClass(1)},
            {"item 2", new myClass(2)},
            {"item 3", new myClass(3)},
            {"item 4", new myClass(4)},
            {"item 5", new myClass(5)},
        }; 

        InitializeComponent();
    }
}

4
আমাকে এক্স: নাম পরিবর্তন করতে হয়েছিল (সংকলক ত্রুটি CS0542)। তারপরে এলিমেন্টনাম সেই অনুযায়ী পরিবর্তন করা দরকার।
জ্যাক মিলার 14

25

গাইয়ের উত্তরটি সঠিক (এবং সম্ভবত 10 টির মধ্যে 9 টি ফিট করে) তবে এটি লক্ষণীয় যে আপনি যদি ইতিমধ্যে এর ডেটা কনটেক্সটটি আরও একটি স্ট্যাক সেটআপ করে রেখেছেন এমন একটি নিয়ন্ত্রণ থেকে এটি করার চেষ্টা করছেন, আপনি যখন ডেটা কনটেক্সট সেট করবেন তখন আপনি এটি পুনরায় সেট করবেন নিজেই ফিরে:

DataContext="{Binding RelativeSource={RelativeSource Self}}"

এটি অবশ্যই আপনার বিদ্যমান বাইন্ডিংগুলি ভেঙে দেবে।

যদি এটি হয় তবে আপনার পিতামাতার পরিবর্তে আপনি যে নিয়ন্ত্রণটি বাঁধতে চেষ্টা করছেন তার উপর রিলেটিভসোর্স সেট করা উচিত।

অর্থাত্ ব্যবহারকারীর নিয়ন্ত্রণের বৈশিষ্ট্যগুলিকে আবদ্ধ করার জন্য:

Binding Path=PropertyName, 
        RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}

ডেটা বাঁধাইয়ের মাধ্যমে কী চলছে তা এখন দেখার পক্ষে কতটা কঠিন হতে পারে তা দেওয়া হলেও, আপনি যদি সেটিংটি RelativeSource={RelativeSource Self}বর্তমানে কাজ করে দেখেন তবেও এটি মনে রাখা উচিত :)


4
সিলভারলাইট 4 ফাইন্ডএন্টস্টোরকে সমর্থন করে না। তবে এটি আপনাকে এইভাবে করা দরকার আপনি এই সাইটে বর্ণিত ফাইন্ডএন্টস্টোরকে বাস্তবায়ন করতে পারেন। http://blog.thekieners.com/2010/09/08/relatives
Source

7

আরও কিছুটা স্পষ্টতা: 'গেট', 'সেট' ছাড়াই সম্পত্তি আবদ্ধ হতে পারবে না

আমি অনুরোধকারীর মামলার মতোই মামলার মুখোমুখি হয়েছি। বাইন্ডটি সঠিকভাবে কাজ করার জন্য আমার অবশ্যই নিম্নলিখিত জিনিসগুলি থাকা উচিত:

//(1) Declare a property with 'get','set' in code behind
public partial class my_class:Window {
  public String My_Property { get; set; }
  ...

//(2) Initialise the property in constructor of code behind
public partial class my_class:Window {
  ...
  public my_class() {
     My_Property = "my-string-value";
     InitializeComponent();
  }

//(3) Set data context in window xaml and specify a binding
<Window ...
DataContext="{Binding RelativeSource={RelativeSource Self}}">
  <TextBlock Text="{Binding My_Property}"/>
</Window>

10
'পেতে' এবং 'সেট' না করে কীভাবে আপনার সম্পত্তি থাকতে পারে? এটা কি ক্ষেত্র হবে না সম্পত্তি হবে না?
kjbartel

0

আপনার কোডের পিছনে, উইন্ডোটির ডেটা কনটেক্সটকে অভিধানে সেট করুন। আপনার এক্সএএমএল-তে আপনি লিখতে পারেন:

<ListView ItemsSource="{Binding}" />

এটি অভিধানে তালিকাগুলিকে আবদ্ধ করবে।

আরও জটিল পরিস্থিতিতে, এটি এমভিভিএম প্যাটার্নের পিছনে কৌশলগুলির একটি উপসেট হবে ।


0

একটি উপায় হ'ল একটি পর্যবেক্ষণযোগ্য সংগ্রহ (সিস্টেম.কালেকশনস.অজেক্টমোডেল) তৈরি করা এবং সেখানে আপনার অভিধানের ডেটা রাখা। তারপরে আপনার পর্যবেক্ষণযোগ্য সংগ্রহটি আপনার তালিকাবক্সে আবদ্ধ করতে সক্ষম হওয়া উচিত।

আপনার এক্সএএমএল-তে আপনার এরকম কিছু হওয়া উচিত:

<ListBox ItemsSource="{Binding Path=Name_of_your_ObservableCollection" />

0

একটি রূপান্তর সংজ্ঞা:

public class RowIndexConverter : IValueConverter
{
    public object Convert( object value, Type targetType,
                           object parameter, CultureInfo culture )
    {
        var row = (IDictionary<string, object>) value;
        var key = (string) parameter;
        return row.Keys.Contains( key ) ? row[ key ] : null;
    }

    public object ConvertBack( object value, Type targetType,
                               object parameter, CultureInfo culture )
    {
        throw new NotImplementedException( );
    }
}

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

public class BindableRow : INotifyPropertyChanged, IDictionary<string, object>
{
    private Dictionary<string, object> _data = new Dictionary<string, object>( );

    public object Dummy   // Provides a dummy property for the column to bind to
    {
        get
        {
            return this;
        }
        set
        {
            var o = value;
        }
    }


    public object this[ string index ]
    {
        get
        {
            return _data[ index ];
        }
        set
        {
            _data[ index ] = value;
            InvokePropertyChanged( new PropertyChangedEventArgs( "Dummy" ) ); // Trigger update
        }
    }


}

আপনার .xaml ফাইলটিতে এই রূপান্তরকারীটি ব্যবহার করুন। প্রথমে এটি উল্লেখ করুন:

<UserControl.Resources>
    <ViewModelHelpers:RowIndexConverter x:Key="RowIndexConverter"/>
</UserControl.Resources>

তারপরে, উদাহরণস্বরূপ, যদি আপনার অভিধানে কোনও কী প্রবেশদ্বার থাকে যেখানে কী "নাম" থাকে, তবে এটি আবদ্ধ করতে: ব্যবহার করুন

<TextBlock  Text="{Binding Dummy, Converter={StaticResource RowIndexConverter}, ConverterParameter=Name}">

0

আপনার সম্পত্তি "উইন্ডোনেম "টিকে নির্ভরশীলতা হিসাবে তৈরি করুন এবং বাকিটি একই রাখুন।


0

আমার ঠিক একই সমস্যাটি ছিল তবে আমার কারণটি ছিল না কারণ আমি একটি স্থানীয় ভেরিয়েবল সেট করছিলাম ... আমি একটি শিশু উইন্ডোতে ছিলাম, এবং আমার একটি সম্পর্কিত ডেটা কনটেক্সট সেট করা দরকার যা আমি উইন্ডো এক্সএএমএল-এ যুক্ত করেছি।

<Window x:Class="Log4Net_Viewer.LogItemWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    DataContext="{Binding RelativeSource={RelativeSource Self}}"
    Title="LogItemWindow" Height="397" Width="572">

0

আপনি এক্স: রেফারেন্স ট্রিক চেষ্টা করতে পারেন

<Window ... x:Name="myWindow"><ListBox ItemsSource="{Binding Items, Source={x:Reference myWindow}}" /></Window>

0

কোডটির পিছনে আবদ্ধ হওয়ার এটি আমার উপায় (সম্পত্তি দেখুন DataTemplateSelector)

public partial class MainWindow : Window
{
  public MainWindow()
  {
    this.DataTemplateSelector = new MyDataTemplateSelector();

    InitializeComponent();

    // ... more initializations ...
  }

  public DataTemplateSelector DataTemplateSelector { get; }

  // ... more code stuff ...
}

এক্সএএমএল-তে RelativeSourceপূর্বপুরুষদের মাধ্যমে সম্বোধন করে রেফারেন্স করা হবে Window, সুতরাং আমি আমার Windowক্লাসে রয়েছি এবং Pathঘোষণার মাধ্যমে সম্পত্তিটি ব্যবহার করি :

<GridViewColumn Header="Value(s)"
                CellTemplateSelector="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataTemplateSelector}"/>

DataTemplateSelectorকল পরিবর্তনের আগে সম্পত্তি নির্ধারণ সম্পত্তির পরিবর্তনে কোনও যোগাযোগ চালানো না হওয়ায় বাস্তবায়ন বা InitializeComponentপ্রয়োগের অনুপস্থিতির উপর নির্ভর করে ।IPropertyChangedDependencyPropertyDataTemplateSelector

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.